Simple Custom Settings Fields for Give WP Donations Plugin

My previous post about Give was an intro to building a payment gateway for the plugin.  If you’ve built extensions for Give or are starting to then you’ve probably run into the settings fields API for adding a variety of inputs.  The options are limited and there are often times a need for custom fields.

How Give’s Settings Fields Work

In the class file class-admin-settings.php located in give/includes/admin/ the function output_fields handles displaying different types of fields registered.  If you are here you probably know the standard format for adding a settings field in your code:

settings[] = [
   'name'    => __( 'Select an Option', 'my-text-domain' ),
   'desc'    => '',
   'id'      => 'select_box_1',
   'type'    => 'select',
   'options' => [ 'op1' => 'Option 1', 'op2' => 'Option 2' ],
]

That adds a select field with a couple options.

As you add settings to an array they will be displayed in the same order in a Give formatted html table.  It appears they were using CMB2 but have since deprecated it.  I’m not 100% sure but there are remnants of it in the plugin.

Creating A Custom Field

Within the output_fields function I mentioned above there is a switch statement on the field type.  This goes through all the type options default in Give and outputs the field content based on type.  After all the case type options the default is a sweet do_action( ‘give_admin_field_’ . $value[‘type’], $value, $option_value );  This is how you do what you want to do with a custom field.

One thing I really needed when building an extension was a way to have inter-woven sub headers for form options.  I could not find a way to just output a title.  The type field title that’s default to Give outputs the top of a table with it as it’s meant to be, that’s right, at the top lol.

Let’s start with an example of creating a simple sub title output.

Remember, the form settings fields are all in a table so you need to use a table row to output your field.  Now we can add this subtitle between fields by using:

$settings[] = [
   'id'   => 'my_settings_subheader_one',
   'name' => 'Custom Sub Header Section',
   'type' => 'my_custom_subtitle',
];

Voila! We have a custom field in Give settings.  The type is set to what comes after give_admin_field_ in the add_action of our sample.

Custom Give Settings Fields Subheader and HR
Here I have two custom fields, a subheader field and a horizontal rule field

Saving Custom Field Data

Saving is pretty straight forward as well.  The example below is kind of pointless as Give already has a text box type but it shows how you’d go about saving your data in a custom field.

The key is figuring out how to structure your action’s name.  Give uses the settings page followed by _save_ followed by the tab you are on.  Here’s their documentation on it followed by an example.

/**
 * Trigger Action.
 *
 * Note: action dynamically fire on basis of setting page slug and current tab.
 * For example: if you register a setting page with give-settings menu slug and general current tab name
 *              then action will be give-settings_save_general
 *
 * @since 1.8
 */
do_action( self::$setting_filter_prefix . '_save_' . $current_tab );

What The F**k Are You Doing Wordfence?

I’m not even going to link to the blog post they put up recently, but I’m sure you can find it if you want.

So a dude bought some plugins and in those plugins snuck some links/urls to spam sites he owns.  Yes, it’s shady and awful practice.  Is it illegal? No.  Is it ok to call out the plugins so people ditch them? Absolutely.

But is it cool to post their full name a bunch of personal information and photos? FUCK NO.  That is entirely uncalled for and fucked up.

This guy isn’t pushing malware.  He’s not hacking your mainframe, bro.  He’s doing some sleezy back linking shit.  There is not a single thing about that which makes it appropriate for WF to put screen grabs of his LinkedIn profile on their post.

Wordfence is starting a witch hunt.  I remember when those got banned on Reddit and you know why? Because it’s wrong.  It can quickly escalate to mass harassment or worse. You don’t put up other people’s personal information on the web.  Period.

I am absolutely flabbergasted that they had the gaul to put up a blog post like that.

How To Build A 3D Chain/String/Rope in SceneKit with Swift

I decided to learn Swift.  I’ve always wanted to do some 3D game coding but have never taken the initiative learn a language that’s good for that.  I’ve had some time in the evenings free up recently and took advantage.

Now I’m still learning Swift.  I’ve only been messing with it for two weeks.  My whole goal since starting has been to make a bimini ring toss game.  If you’ve never heard of it, it’s popular in craft beer pubs.  There’s a metal ring that hangs from the ceiling on a string.  You pull the ring back and try to land it onto a hook on the wall.

SCNNode Shapes

There’s a few basic shapes provided in SceneKit that you can use to start building.  I used a SCNTorus for the ring.

Like I said, I’m still learning, but here’s the gist of my understanding.  SCNNodes are the visible objects you can manipulate in the 3D world.  You add them to an SCNScene which is the world your 3D app lives in.

You can’t see the SCNNodes you add until they have shape so you need to build an SCNGeometry and add it to your SCNNode.  The geometry can be built easily using some pre-built shapes like SCNTorus or SCNBox and a few sizing parameters.

Your nodes aren’t going to do much either until you add a SCNPhysicsBody to them.  I’m still trying to wrap my head around the physics stuff but I get the basics which is all you need to build something like this rope.  By making a physics body object and using .dynamic for type and nil for shape it just defaults physics boundaries to the shape of the node and interacts with other nodes that have physics bodies.

Faking A String

So googling “Swift 3D string” didn’t help me at all.  Seeing as string is a global keyword for nearly every coding language, there were no results about an actual twine string being created in 3D.

I started looking for “rope” and found one codebase in c# that built a rope by chaining a bunch of cylinders together that had pivot joints connecting them.  Made sense!

I want to learn Swift though, this meant I needed to build this functionality myself but at least I had a reference now.  Let’s start by picking our shape.  Since I wanted more of a string than a rope I went with spheres.  The code example here has them bigger than they will be when the game is ready but it’s good for getting the functionality built.

I put this into a class.  The full repo for this project can be downloaded and run in xcode 8 or newer.  I create what I call links in the rope.  I start with my base link called rope on init since it will be the main point of the whole object.  Then I have a function for creating link nodes.

It’s important to note I’m using a radius of 0.1.  I’m still not completely comfortable with these units, I’m trying to figure them out, but relatively they make sense.

Next, in the game’s main view controller I generate my rope and all the links in a loop and store them in an array called links.  I do this because I wanted to add all my nodes to the scene in the same block of code.  It’s not required to do that but I like the organization.

The SCNPhysicsBallSocketJoint class took me the longest to find and learn it’s what I need to connect all these pieces together.  Implementing it correctly took me some time but the logic makes sense when you really think about it.

Coordinates in SceneKit

Your SCNScene object has coordinates for specific points in x, y and z format.  x = horizontal line, y = vertical line and z = depth (near/far) line.  Now your SCNNode’s ALSO have x, y and z coordinates for points on the actual node.  This can get confusing so take your time getting positioning of objects correct.

For the objects, we don’t need to set a position.  Everything will be spawned at 0, 0, 0 which is right in the middle.  You should add a SCNFloor that’s got a -y position so when gravity turns on your objects don’t just drop down into nothingness.

SCNPhysicsBallSocketJoint requires two SCNNode’s passed to it and it needs a x,y,z point on each node to connect them together.  So bodyA is our link and bodyB is the previous link created in the loop.  Using an SCNVector3 object we build the x,y,z coordinates.

When nodes are created they default to having the coordinates 0,0,0 right in the middle of the object.  Remember our spheres are 0.1 radius.  That means we want out point of connection to be on the top of one sphere and bottom of the other.  So we usr -0.05 on one link and 0.05 on the other link for x, y and z.  Now that I think about it a radius is half the width of our sphere so this number should be 0.1 but 0.05 works so maybe I’m wrong about where the default point is.  Needless to say, you will have to do some math and toy with these numbers.

When you build your joint you have to add it to the SCNScene as a behavior using the addBehavior() method.

Dive In

Finally, we add all of these items to the SCNScene as children and we are set.  They all need to be child nodes of the same parent node, I use on called Holder that I created.  It’s an empty node with no geography so you can’t see it, it’s just like a container to keep them all related to each other.

Check out the full repo and toy with it if you want.  You can see that I have a ring object I attach to the end for my bimini game.  I toy with mass on some nodes as I think that helps the ring feel heavier in the game world.  I have a ceiling for attaching the rope and so on.

https://github.com/ChrisFlannagan/iOS-Bimini-Ring-Toss

Fix for iTunes Store Rejected – This bundle is invalid – The Info.plist file is missing or could not be parsed

Did you get the below email after trying to submit your NativeScript iOS app to iTunes Connect?

Dear developer,

We have discovered one or more issues with your recent delivery for “#####”. To process your delivery, the following issues must be corrected:

This bundle is invalid – The Info.plist file is missing or could not be parsed. Please check it for embedded control characters.

Once these issues have been corrected, you can then redeliver the corrected binary.

Regards,

The App Store team

It can be really irritating but the fix is pretty simple.  This happens when odd characters or weird adjustments are made dynamically to the plist.info file attached to your bundle.  To get rid of this annoying rejection you should do a few things.

  1. Make sure you are setting as much info as you can manually in your app/App_Resources/iOS/info.plist file.  This file is used to generate the xcode.project file’s included plist.  Avoid adjusting the generated plist.info file as much as possible and do this pre-emptively before each build including updating your CFBundleShortVersionString and CFBundleVersion keys to latest version.
  2. Now runs tns platform remove ios then re-add with tns platform add ios
  3. Finally run tns prepare ios

You should be good to go and no more rejection (for that at least)!

Mentors Series #1: Richard Earls

I have a lot to say about mentors.  I would not be where I am today without them.  I didn’t even realize they were mentors until after the fact.  I remember being in my late teens and early 20’s and people would mention finding a mentor.  I never looked for one, I thought the whole concept was strange.  Like, what’s the difference in a teacher and a mentor?

But at the ripe age of 33 I know the difference.  A mentor is a lot like a teacher but they take it a big step further, a really big step.  They take an interest in seeing you better yourself.  Not a light “I want to see you do good” interest, but a deep caring in you getting something out of what you are after.

Teacher’s also teach people who really don’t care about the subject.  To get a mentor you have to be passionate about the subject matter.  So I’m starting this series with Richard.  I’m going to leave last names and identifying details out of the articles unless I’m given explicit permission to use their full names.

Getting Into Web Development

When I was 21 I got married and moved to Germany with my military wife.  She worked a lot and worked really hard.  Her income was guaranteed and I needed to provide as well.  I’d made money building websites and I wanted to try and do it full time but this meant finding clients.

Before I moved over seas I was living in Asheville, NC and had listed myself on a couple freelancer websites.  I showed up in searches for Asheville web developers.  I got an email from Richard Earls shortly after I got to Germany.

Richard was contracting for a large organization that provides services for travel agents (I think that’s what they did at least).  He wanted a Macromedia Flash application that was pretty neat on paper.  It was kind of like a forum but the UI looked like a computer Desktop and all the forms were represented by icons that could be moved around and sorted.  If you double click on one it works like a folder and opens a window with sub forums and so on.

Also, there was an entire custom CMS that managed all the forums and users.  It was wildly complex and I was a terrible coder.

When you double clicked a forum there were topics and you could create, comment, reply and more.  I had never built anything even CLOSE to this complex but I told Richard on our first phone call, “Yea, I can totally do that.”  The cold sweat set in but I charged at the project and built it.  Kind of.

First Project

I believe we said $6,000 for the project.  I got $3k down and the other was to be paid on delivery.  I built the system but as the project moved along the scope started changing.  I didn’t know what scope was back then so I just went with it.  I built something really freaking cool but my code was spaghetti.  Anything Richard found wrong I’d patch with more spaghetti and when things didn’t work I blamed it on anything other than my own skills.

Richard and I had a very intense phone call one night.  I remember it pretty clearly: Where I was standing, what was going on in my head, the fear of saying “no” and “pay me.”  In the end I got paid, I don’t think the project ever went live anywhere though.  I figured that was going to be the end of my relationship with Richard but I was way wrong.

Growing A Relationship

Richard gave me more work.  I’m not sure why but if I were to take a guess it would be communication.  My father was a preacher and public speaker and I definitely got some of that from him.  I take pride in my communication skills and I find that getting clients is a lot easier when you can have a good conversation.

I flew back to the states two times for my last two college semesters.  When I got to Asheville the first time Richard and I got together in person at his condo.  He sketched out on paper his concept for a website.  He called it TravelResearchOnline.com (TRO).  We spent some time going over it, throwing out ideas and how to turn it into a business.

I dove in on the project and Richard paid me by the hour (I charged $17/hr).  One day we launched TRO.  It was damn exciting for me and Richard hit the floor running getting traffic and sponsors.  Richard still runs that website today, over a decade later as one of his main sources of revenue.

I messed up often.  I wrote hacky code but I always managed to make things work.  Bugs happened, things broke and Richard always gave me a kind nudge to get shit working again.  He was firm often but never angry like our first project when things hit the fan.

A Mentor

What made Richard a mentor? Richard looked out for me.  He paid me often, if I needed advance payment for future work he didn’t bat an eye.  He pushed me to do more and be better.  He constantly checked on me personally and even shared things happening in his personal life.

He was a friend.

And he still is.  I posted on Facebook recently about needing some advice on some personal stuff and he hit me up right away in chat and told me to call him.  I grew a lot all while working for Richard almost daily.

I’m estimating years here but I’d some from around the age of 21 to 27 I worked for Richard constantly.  We built a ton of cool projects.

I remember in 2009 when I was in grad school at Syracuse and we were building this flash based digital travel expo.  It was a really awesome concept we brought to life.  But I was sitting in Media Law class and got a text from Richard in all caps.  Something along the lines of “TRO TRAVEL EXPO IS DOWN!” and this was a couple hours after we launched.  It was getting crazy amounts of traffic and I knew nothing about coding for performance or server setups yet I was setting up $225/month dedicated servers for him at SoftLayer.

Even after that Richard never stopped giving me work or being a friend.  And that’s Richard Earls: Travel junkie, Thinker, Business Man, Friend and Mentor.

I got a job as the Webmaster for Sarasota Memorial Hospital when I finished grad school in the Summer of 2009.  I still freelanced for Richard for a couple years but slowly I trickled away from any freelance.  And around 2010/11 I wrote my last lines of code for him.  I can look back on that period of my life and see clearly how it was a big part of molding who I am today.

Thanks Richard 🙂

NativeScript iOS Push Notifications & How to Get Your Device Token When Testing & Debugging in Xcode 8

I found all the articles and frameworks and this still took me quite some time to figure out.  As far as I can tell this is easiest to do using Xcode 8.  Some preliminary items you’ve probably already taken care of if you’ve found yourself here:

Ok, you should be ready to get busy.

Adding The Push Plugin Code To Your Project

From what I can tell it’s not so important where this code is added but seems ideal to put it in the main page js file, the first that loads.  You need to use an observable and bind it to your page.  I had an app that was well into version 2 that I wanted to add push notifications to.  It was setup as many examples are from a year or more ago using

exports.loaded = function(args) { 
  main code here that is run when the first page is loaded  
}

All the examples online use a main-page-view.js observable that’s instantiated in the other main js file and it’s all very complex.  What it boils down to is you need to reference the main observable that’s being bound to your page in the var self = xxx line of the push notifications example code.  In its shortest form you would do something like this:

What’s super import here is the var self = pageData.  We are putting our observable into a variable called “self” that is used in the push notifications code from the readme.

I was just copying the code into my exports.loaded function and kept getting an error like self.set is not a function and was getting really irritated.  So do what I did above or start a fresh project and copy from the sample push plugin repo here.

Getting Your Device Token

In order to test notifications you need to run your app on an actual device.  So plugin your iPhone or iPad and get ready to run your app on it through either Xcode or tns command line.  I always get confused on how to select the right device on command line so I just use Xcode.

You will also need to make sure you have all the example code in place for registering your device.  I’ve built something you can copy here, just make sure that exports.loaded is initiated on the first page load.  The main xml would look like this in the top tag:

<Page xmlns="http://schemas.nativescript.org/tns.xsd" loaded="loaded">

I’ll also embed the full javascript sample code at the bottom of this post so you don’t have to click out of here.

Now you need to get your device token from your iphone/ipad which you will need to use in an app like Easy APNs Provider in order to send test notifications to your phone.  I could not find any functionality in the nativescript plugin but on the link I shared earlier the fella shows how to do it in swift.  These lines here:

func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
    print("DEVICE TOKEN = \(deviceToken)")
}

You can see the long ass function name there.  I found that function in the nativescript plugin files in node_modules.  So you need to temporarily edit (I know, I know) the file and add a console.log to it.  In node_modules/nativescript-push-notifications/push-plugin.ios.js on, at least in the current version, line 41 you will see

var token = result.userInfo.objectForKey('message');

Under that add a console log:

var token = result.userInfo.objectForKey('message');
console.log(token);

Now when you run the app and accept the push notifications alert it will log in your terminal the device token.  DO NOT FORGET to edit that console log out.  Gotta keep them node_modules pure ya know.

Testing It Out

If you did everything right you can use the app I linked to earlier, Easy APNs Provider, and run some tests.  It worked flawlessly for me once I got the code running.  Good luck! Hit me up if you get stuck @ChrisFlanny.  Here’s a full sample code for doing a simple implementation inside an exported function:

Run A Quick, Local WP_Query Injection With A Closure Through Post Clauses Filters

We use the posts to posts (p2p) plugin a lot for building relationships between posts and post types. Occasionally you will have a query to get connected posts that will return multiple copies of the same post. So I worked out this method to handle that efficiently.

This method can be used for more than just query injections but that seems to be where I find myself doing it most. Sometimes you need a tweak to a get_posts or a new WP_Query but it’s so localized to the particular function it is in that it’s best to just take care of it there. No need to build out a class to handle it, just give this a shot.

Being Efficient

When coding, avoiding unnecessary sql queries and loops with conditionals is at the top of the list in keeping your site’s speed as optimized as possible. I had a query that was pulling in duplicate copies of posts thanks to the way p2p works. I could certainly just loop through the results and build a new array of distinct articles but that would be wasting processor power and making my query return far more than I needed.

I needed to do this right. So my thought was to filter into the query and adjust the sql before it ran. There’s a multitude of ways to do that but I also felt that this was so unique to this particular function that building out a class or a helper function to do it was unnecessary and would involve too much code for a simple task.

So the goal is to slap an sql clause filter on before the query and make sure that filter was removed before any other queries ran.

Choosing The Clause Filter

So the simplest filter would be to use ‘posts_distinct’ and return “DISTINCT.” This puts a DISTINCT string right after the SELECT statement. It works great for a typical query but when you have a complex JOIN query sometimes it just won’t work.

I toyed with the ‘posts_fields’ filter, but didn’t get far and never got the results I was after. I finally realized the sql I was invoking through p2p and WP_Query was needing a GROUP BY piece to group the results by post ID and remove duplicates.

function groupby( $groupby ) {
    global $wpdb;
    return "{$wpdb->posts}.ID";
}

Now I just needed to implement my filter somewhere.

Add Filter, Remove Filter

We need to make sure our filter only hits this single query we are running. What we can do is this:

  1. Build a closure: Assign a variable’s value a function to handle the groupby needs.
  2. Add a filter that executes our closure.
  3. Run our get_posts() or new WP_Query.
  4. Remove the filter.

It’s actually super simple and efficient. Here’s the code I used:

By adding the filter right before get_posts() and removing it right after we are making sure that filter only hits the query executed by get_posts().  Also, by storing the function as a closure in the $distinct_ids variable we are able to target it in our add_filter and remove_filter with ease.

WP_Query Filters

There’s a whole bunch of cool filters you can tap into to customize the sql query before it executes.

  • posts_fields – Filter the fields right after the SELECT of the query
  • posts_join – Filter the JOIN
  • posts_orderby – Filter the ORDER BY
  • posts_where – Filter the WHERE statements
  • posts_distinct – Use return “DISTINCT” to avoid duplicates (unless you have a situation like mine here).
  • posts_clauses – This one is awesome.  It passes in a single parameter which is an array of all the above and you can adjust them all in the same function.

This shit is really powerful and when you start reaching more advanced levels of WordPress development you’ll find yourself using them regularly.  Check out my co-workers blog post about building out a query for calculating distance between two geo coordinates.  This was what taught me a lot about this stuff and it’s really amazing.