Remove Item from PayPal Invoice with the REST API

I’m building a pretty crazy system right now around the PayPal Invoice REST API.  I want the owners of the site to be able to adjust all sorts of stuff on invoices whether the status is DRAFT or SENT.  If PAID, no go.  I’m going to give them the option to copy and cancel the original if that’s possible but I haven’t dove that far in yet.

But what I did need at this point was for them to allow users and admins to adjust an invoice by removing items.  So I google searched without much luck then finally looked through the API’s code to find what I needed.

PayPal Invoice Class

Inside the class for Invoice.php is a method removeItem().  Well, I tried this and kept getting a 400 error with no description of why it wouldn’t work.  I was using a foreach loop.

foreach ( $invoice->items as $item ) {
    if( blah blah ) {
        $invoice->removeItem( $item );
    }
}

This was just not working and there were no clues as to why.  I tried adding a count variable $cnt and using removeItem( $invoice->items[ $cnt ] ) but that was producing the same error.

Adjust The Quantity

So I finally settled on just changing the quantity to 0 and, low and behold, that worked just fine.  So end of day, the line item will still be there but you can set the quantity to 0 and it will charge nothing for it.  Final code was basically:

foreach ( $invoice->items as $item ) {
   if ( strpos( $item->name, 'Item ' . $id . ':' ) !== false ) {
      $item->setQuantity( 0 );
      $invoice->update( $api_context );
   }
}

Stuck WooCommerce Cart Counter: Clear Cache After Add To Cart

Do you have a counter on your WooCommerce site that shows the user how many items are in their cart? We do, it looks like this on every page:

cart-counter-woocommerce

We do this with a very simple line of code in the header.php file of our theme:

CART | <?php echo sizeof( WC()->cart->get_cart() ); ?>

This gets a count of items in the cart array.  It is very simple, clean and efficient, unless you having a caching plugin installed.  If you do, then on pages that are fully cached the cart number will not be regenerated until the cache is cleared.

Clear Cache Dynamically

I use Comet Cache on our site.  It’s a killer caching plugin and the free version has so many features out of the box it’s incredibly useful.  So how do we clear this number? Simple.

In our functions.php file we hook into the woocommerce_add_to_cart and simply clear the cache using the object comet_cache‘s built in clear() method.  If you are using a popular, modern caching plugin it probably has a function that works very similar to this and you can call it here as well.

https://gist.github.com/ChrisFlannagan/003d3efa9cb2aec88b0e54b654e20c77

Use NativeScript Plugin nativescript-background-http To Send And Store Camera Pictures On PHP Server

I searched and searched and asked on slack and asked on the NS FaceBook group and everything I could think of to figure this out.  I finally pieced it together and it’s working.  So do you want to let your app users take a picture with their camera, or use one in their library for something and you need that photo stored on your web server? We let users take before/progress/after pics from using our device.  We want to store these photos so we can see results ourselves and request use from our users for advertisements.  So here’s how you do it.

nativescript-background-http

You need to make sure and import your camera ui and also this plugin.  It’s extremely awesome and works great.  You can get it by running

tns plugin add nativescript-background-http

EDIT: For some reason when I put this on an actual device it wouldn’t save the photos.  When on the actual phone it has a problem with using knownFolders.currentApp() and a custom folder, so I change that line from

fs.knownFolders.currentApp().path + /saved_images;

to

fs.knownFolders.documents().path;

and it worked just fine.

After setting that up use the below code, or whatever parts of it you’d like, to make the NS function and push the upload to your server.  A couple notes though, I use a folder called /saved_images in my /app project directory to store the files before sending.  I’m not sure this is necessary but I wanted to resize to a maximum of 800px wide or height while retaining proportion.  It is extremely important this directory is created if you use this filepath or your script will fail and you won’t know why because error logging here doesn’t do anything.

Also, I store a global configuration variable for my api’s URL, so I use url: config.apiUrl in my request options.

https://gist.github.com/ChrisFlannagan/e9e32428935076419f24aec6a30a7381

Saving The Image In PHP

So the config.apiUrl points directly to my php file (ex:server.com/apifile.php).  In this file you need to access file_get_contents(‘php://input’) to access the streamed data coming in.  This is how you work with forms submitted using content type “application/octet-stream” to get the file data.  With this data you can simply save it however you’d like using file_put_contents.  There’s other security concerns you will need to address that I’m not going over here as they are different all different applications of this process.  But here’s a quick, simple line for saving the image to a /uploads/ directory:

$all_headers = apache_request_headers();
$newimg = file_put_contents('uploads/' . $all_headers['File-Name'], file_get_contents('php://input'));

Now your image has been saved!

Additional User Data Needed

If you are storing this image and attaching it to a user or any other kind of data you can pass these as header fields just as you did the File-Name.  In your JS just under the line:

"File-Name": filename

Add a comma and put the next field you might need such as:

"File-Name": filename,
"Email-Add": email

Enjoy!

Full Screen jssor Slider Exact Window Width & Height

I’ve been working on a program for my side job that is supposed to have lots of slider like features between content with LOTS of content.  My favorite slider libray, because it’s got SO much functionality for devs is jssor.

One thing I could not find a proper solution for was making a full screen slider that would work on any screen or device (with a modern browser).  So, I thought and thought and came up with a solution.

So there’s no way to set jssor height by percentage or parent height and keep the width proportional.  I tried everything I could but it absolutely must be pixels.  There are some options that set it but the width is then off.  Seriously, I tried everything.

So What If We Set It By Pixels?

I mean, it is a php site.  So I came up with an interesting solution.  It’s not bullet proof, especially if the user resizes the window, but it works.

My php starts with this:

session_start();
if( isset( $_REQUEST['wslides'] ) ) {
   $_SESSION['wslides'] = $_REQUEST['wslides'];
   $_SESSION['hslides'] = $_REQUEST['hslides'];
}
if( !isset( $_SESSION['wslides'] ) || isset( $_REQUEST['reset'] ) ) {
   header( "Location: set-dimensions.php" );
}

Here we start a session, then, we see if there’s a query variable called ‘wslides.’  If there is, then we have ‘wheight’ too and we know what pixels to set for our slider.  Bam!

So How Do We Get Those Pixel Dimensions?

Look at the next ‘if’ statement.  If we don’t have a session set for width and height we forward to a page called ‘set-dimensions.php’.  Here’s the full code of that page:

<html>
<head>
   <title>Loading</title>
   <script language="javascript" type="text/javascript">
      window.location.href='index.php?wslides=' + window.innerWidth + '&hslides=' + window.innerHeight;
   </script>
</head>
<body></body>
</html>

It’s just used to set dimensions of window very fast then send back with the query variables.  Now we can build our slider to the window’s width!

<div id="slider1_container" style="position: relative; top: 0px; left: 0px; width: <?php echo $_SESSION['wslides']; ?>px; height: <?php echo $_SESSION['hslides']; ?>px;">
 <!-- Slides Container -->
 <div u="slides" style="cursor: move; position: absolute; overflow: hidden; left: 0px; top: 0px; width: <?php echo $_SESSION['wslides']; ?>px; height: <?php echo $_SESSION['hslides']; ?>px;">
  <div id="slide-welcome">hello</div>
  <div id="slide-goodbye">goodbye</div>
 </div>
</div>

The WP Crowd Podcast: Level’ing Up as a WordPress Developer

I’ve joined the team over at The WP Crowd for the most recent podcast.  I’ll also be blogging over there as well, so keep an eye out for my articles!

Episode 029: Level’ing Up as a WordPress Developer

 

Building an HTML Form Importer for WordPress

Git: https://bitbucket.org/MrFlannagan/better-html-form-importer

I was working on a project for work recently where I had to take an old, terribly-coded, ASP.NET processed HTML form and move it over to WordPress.  This thing had a lot of inputs, selects and such.  Did a quick search for a tool that might help simplify the process.  For one thing, it would save some real time and for another, I HATE doing monotonous tasks.

Well, I had no luck finding anything to help me so I thought, “What if I could build it?”  I love toying with building scrapers and parsers.  I knew this would be sloppy as every crappy HTML form has completely different code, different structures, different mark-up and more times than not broken HTML.

I sketched a few concepts and settled on something that would work with <div> layouts, <table> and whatever else.  Will it work perfect? I knew right away that was not the case, but if I could get 80%, hell 60% right on most then it would save some real time.  And if I built some tools to help simplify fixing the errors, well hell, we saving some serious time, baby!

So what I settled on was this:

  • Recursively loop through all nodes in a block of HTML using DOMDocument.
  • Save current element if it’s just text/characters.
    This part gave me some issues.  I tried using preg_replace to remove all white space and detect if the element is a word but it just wasn’t catching them all.  So I decided to split the whole thing into individual characters.  If looping through encountered a character then it breaks and uses that node as the current element.  Basically this just bypasses any strange white space characters.

    if( 3 == $node->nodeType ) {
        $allchars = str_split( $nValue );
        foreach( $allchars as $achar ) {
            if( ctype_alnum ( $achar ) ) {
                $prevText = $nValue;
                break;
            }
        }
    }
  • If the element is a form input of some sort, create a label input with value of previous textual element (saved as current element in previous step), create an element name input,  and finally create a duplicate of current element with it’s value in a table row and display it.

This way every form element would be displayed with a label best guessing its previous label and allow that to be edited easily.  It would also display an editable field for the name of the element and one for its value.

So far, I’m really happy with the results.  (https://bitbucket.org/MrFlannagan/better-html-form-importer)

My plan is to finish all the different types of inputs (checkboxes, file uploads, etc.) and then add a way to drag and sort them, create additional elements and more.  I’ll give users the option to create a shortcode where they can display it, set if it emails/stores results in database and finally I’m hoping to make use of the Gravity Forms API and allow it to import there and other form plugins I can figure out.

Simple Responsive Slider For Sliding Posts/Pages/Whatever Using the WP Rest API

I have a client that wanted their website to be primarily just the home page.  They also want mobile and tablet users to just be able to swipe through the pages.  I found some potential solutions but they were mostly very large, overly complex plugins for a simple need.  I’ve been wanting to dive into the WP API and I found this to be a great opportunity.  This is VERY basic usage of the WP API, but hey, I’m just getting started.  And please read to the bottom if you are knowledgeable of the WP API as I’m a bit confused on why something I tried did not work.

So here is my simple solution for the sliding pages (works for posts and other post_types as well).

JSSOR

First we need to include a slider library.  I went with JSSOR because it works great with loads of features and is easy to get started quickly.

http://www.jssor.com/development/

I enqueue this in my themes functions.php file

function theme_scripts() {
    wp_enqueue_script( 'jssor', get_template_directory_uri() . '/js/jssor.slider.mini.js', array() );
}
add_action( 'wp_enqueue_scripts', 'theme_scripts' );

build_sliders

Then we have our function for building the slider.  This can be tweaked to your liking, I wanted to have title, featured image and content.  We take in the slider id and height as parameters and we also take in the full url for the WP API request.  We format around the loop through our results with the required JSSOR slider containers.  The jQuery at the bottom is used to make the slider responsive.

/**
 * Build sliders
 */
 function build_sliders( $slider_id, $slider_height, $api_request ) {
 
	?>
	
'; echo '

' . $slide['title'] . '

'; if( $slide['featured_image'] ) { $thumbnail_id = get_post_thumbnail_id ( $slide['ID'] ); $thumbnail = wp_get_attachment_image_src( $thumbnail_id, 'full' ); echo '

'; echo $slide['content']; } echo '

'; } ?>

Finally we make a simple call to our function.  I placed this in the index.php file in my theme. It could easily be built into a plugin/shortcode.

I wanted pages from a specific page category (I used a plugin to add category options to pages: https://wordpress.org/plugins/add-category-to-pages/).

WP API Question

When first building this out I wanted to add the featured image src to the WP API response, I found a site through google that explains how to do it.  But for some reason I did not see any data labeled 'featured_image_thumbnail_url' when testing my api calls.  What gives? I used the code below in my functions.php file.

 function my_rest_prepare_post ($data, $post, $request ) {
	
	$data = $data->data;
	
	$thumbnail_id = get_post_thumbnail_id ( $post->ID );
	$thumbnail = wp_get_attachment_image_src( $thumbnail_id, 'full' );
	$_data['featured_image_thumbnail_url'] = $thumbnail[0];
	$data->data = $_data;
	
	return $data;
}
add_filter( 'rest_prepare_post', 'my_rest_prepare_post', 10, 3 );