Comments On Code

Posts on Programming

Jan 13, 2018

Refining my Process (Part 2)

Isn't synchronicity funny? I ended the last post with my attempt to make myself a dashboard widget that would give me a reminder message to append my hosts file, which I am surely going to forget to do if I don't put a message to future me somewhere. I have a textbook about plugins I've just started, but it was late and the book was downstairs, so I thought I could quickly find a tutorial and copy over code. Which didn't work. And, thus, as it was late, I set it aside for another day.

The following day, I had to run my daughter to a dentist appointment, so I needed a task that I could accomplish on the go. Looking through my RSS reader, I realized I had over 50 starred articles, that I had marked in order to come back to later. Later never arrives. Except that, that seemed like an ideal task to work through on such a day. I have my pinterest board set up to divide Development articles into subcategories so I can easily find resources for given topics of interest. It's more navigable than a random collection of starred articles (and slightly more frequently referenced). I set about saving the links into pinboards.

Lo, and behold, I found a set of articles on linting PHP, primarily for WordPress. Thinking of my recently abandoned attempted plugin, and the many new and wonderful things I would be designing in the future, I realized that this could be a great way to up my tooling and coding game and relieve me of the need to manually edit my code for WordPress standards. No, it won't fix broken code, but it will definitely help keep my code tidier.

Proceeding through the complete tutorial went off without a hitch. Then the following day, I realized that the process as designed, would require me to install the sniffer in every project folder, then run the commands from terminal. First problem, the command used the directory path to execute it, which was less than memorable. Second, I don't need extra build steps or duplicate extraneous directories in all my projects. I needed to streamline the process, ideally within my Sublime Text editor.

Maybe I should rename this blog, "Confessions on Code." The following will display the degree of my ignorance of my own tools I have chosen. These are my breadcrumbs for myself, so when I find myself in similar circumstances in the future, I can recall what worked before and get myself back on track. If you cringe at novice coders making ignorant mistakes, this is your cue to look away now.

I thought that setting up my sniffer in Sublime Text would be as easy as setting up the plugin, distributed by the same folks that developed the PHP_CodeSniffer, Squizlabs. I opened up the settings, went over to my terminal to run which phpcs, only to find nothing. I have nearly no composer experience. I didn't yet realize the command would only run downpath from where composer installed the sniffer. I attempted to use the phpcs command, and terminal gently informed me that I didn't have the package, but I could install PHP_CodeSniffer to access it. So I did. Which was a big mistake.

With a system wide access to the commands, which phpcs worked! So, I edited the settings file to provide the right path to the commands.

Now I needed to reinstall the WordPress standards, which is what this whole project was about. The tutorial I used initially didn't tell me how to set up the WordPress Coding Standards outside of composer. Google directed me to another tutorial which described how to install the WordPress standards. However, since I installed the commands through apt, I couldn't clone the repository into the bin directory. I dropped it in my home directory and attempted to configure the package using that path. Which failed. And gave me errors about not writing to certain files. Which I overrode with sudo as one is wont to do when confused. Then I returned to the Sublime PHP_CodeSniffer plugin settings and tried to set the standard to WordPress. I ran the plugin and nothing happened. I tried it on another file and nothing happened. I ran the linter through terminal, and got a set of error messages. Great!

At least, error messages produce something to Google. Error messages are my friends. Things that do nothing and produce nothing are the problem.

The subsequent course of events are a little foggy at this point. They involved trying many things. I recalled that I had gotten several errors about not being able to write to files that should not have needed a sudo command. I had just upgraded my OS a week before and had had a few issues with packages that didn't upgrade quite right, or dependencies that got locked, etc. I wondered if my permissions were off. I reset my home directory permissions to be sure.

I also thought that maybe I should follow more of the tutorial in which I used to install the WordPress Coding Standards and use those plugins. That lead me to discover I had a much larger problem. I could not get Sublime Package Control to install anything. I had not used Package Control to install the PHP_CodeSniffer plugin, so I didn't discover this earlier.

I found the Package Control Troubleshooting guide and followed the steps for Purging and Reinstalling Package Control. After that, the plugin would install, but disappear on restart. I found a way to turn on those all-important error messages, by turning on debug mode in Sublime Linter. This showed me that the plugin was being removed during set up because Sublime was not finding the gutter theme files.

I installed separate gutter theme files. Nada. I reinstalled Sublime through the package manager. I uninstalled and reinstalled...I complete uninstalled and reinstalled. Nothing worked. Finally, I discovered a comment in a forum to revert Sublime to a Freshly Installed State. It couldn't hurt. The instructions stated to move the data folder. It took another couple searches to confirm that "data folder" was in fact, the entire Sublime Text 3 folder within the .config directory and not a folder within it as the instructions suggest. That worked! I could get the plugin to install and stay!

However, the plugin wouldn't run. I realized that the way I had PHP_CodeSniffer installed, and the WordPress Standards installed, was conflicting with the plugin's functioning. I decided to completely uninstall PHP_CodeSniffer and the WordPress Standards from everywhere and call it a night.

Something magical happens when the brain rests over night. I woke up and knew exactly what to do, and within 15 minutes of waking up, before taking children to school, I had the PHP_CodeSniffer installed globally, the WordPress Standards cloned into the directory and everything running in terminal again. I used the same Sublime Linter tutorial I had used before, but using the proper Linux commands, as on this guide to globally installing PHP tools with Composer. I added the directory to Path, as instructed on the guide, with one mistake I would discover later on.

The Sublime Linter plugin installed. The accessory phpcs plugin also installed, and properly accepted my path and WordPress standards. Finally, I decided to try and reinstall the original PHP_CodeSniffer plugin, and that worked as well. I am currently running both because the one places markers in the files and the other creates a verbose output that explains what the error is.

The final hiccup I discovered after a restart. I didn't understand what the guide meant by saving the PATH to the bash profile. So, the PATH was only good for that session. Once I restarted my computer, the PATH to my composer/PHP_CodeSniffer installation was removed, and everything failed again. Thankfully, I had a suspicion and quickly found the solution with instructions on stack overflow, How to place the ~/.composer/vendor/bin directory in your PATH.

Now that I have a better idea of how Composer and Sublime Text plugins both work, I'm excited to add a few more tools to my workflow. Here's to hoping next week actually results in the production of something useful.

Jan 12, 2018

Refining my Process (Part 1)

As my youngest is only three years old, my business load has been low-volume, the majority of which is the maintenance of current clients. Building out new sites has only been one at a time. Given that, I didn't give much thought to setting up my environment, other than setting up a locally hosted WordPress for the sites on which I run WordPress, and a cross-platform capable text editor (my hardware consists of an iMac, out of family traffic, and a laptop running dual-boot Windows and Linux Mint installations, for portability and diversity of OS).

I am expanding into WordPress Plugin development. Knowing that occasionally Themes and Plugins do not play nicely together, I wanted to create a set up into which I could install as plain a starter theme as possible, and keep it purely plugin focused. It wasn't until after I set up the second local WordPress, that I realized I had a pain point that would amount to a large scaling problem once I try to kick my business into second gear. Until now, I would set up a new project on the existing installation, add new posts and pages that reflect a particular client's needs, install the theme or build it up, customizing it as I go. New client, all the previous gets reset, and the new project begun.

Obviously, this is completely unworkable for working more than one site at a time. On the occasion that I have had to return to a project to make adjustments, it is a large hassle to manually revert everything the way it needs to be for that project. I often end up making some modifications directly to the live site, then save them back to my github repository, which is a hazardous way to develop. It leaves me wondering and second guessing whether I remembered to update my repo properly. Thankfully, I have not yet had a crisis, but it really is only a matter of time.

I began pondering my current set up. What if I could set up a project and leave it set up? What if I could just spin up a new install for each new client/project? Duh! That is a multisite environment. Ah-ha.

I have never worked with multisite and set about to figure out how to install it. I discovered that decisions needed to be made right off the bat. Do I want subdomain structures? Or subdirectory? The first would complicate set up, but the second seemed prone for more confusion down the road. The first would require a fresh install, while the second would allow me to continue using my existing set up. The first would require me to look up more tutorials on how to set it up, since the tutorials I had found tended toward the second (to avoid the rabbit trail of Apache customizations). In the event I had multiple sites open at once (always), I want the URLs to be obvious at a glance, so I went with the first.

There are really only a few steps: 1. edit the Apache hosts file, 2. install a fresh WordPress and turn on multisite, 3. select the subdomain option, and 4. insert a new subdomain into hosts for every subdomain. The fourth one can be set up to be automatic in older Linux environments, using wildcard DNS, but it looks like my newly upgraded Mint, running on Ubuntu 16.04, doesn't have a simple way to do that. Another problem for another day. I found both these tutorials helpful,

How to Setup a Localhost WordPress (Sub-domain Multisite) Environment and The Ultimate Guide to WordPress Multisite. I found a slight complication in my personal set up, because I do not solely work in WordPress. On my Linux system, my local Apache folder contains other sites in addition to my WordPress installation. I originally had WordPress in a secondary directory. That set up did not work with the subdomain installation, although it worked just fine with the subdirectory based multisite. Once I chose the top level directory for the installation point for WordPress, the steps proceeded smoothly. I combined all my non-WordPress projects into a new directory, which I can still navigate on my localhost, and step out of the WordPress environment.

Since I had an existing WordPress installation, I found this tutorial to help guide my process through converting that site into the new multisite set up: How to Move a Single WordPress Site into a Multisite Network.

Unfortunately, I have not had a chance to dig into my new environment, set up all my clients' sites, and pat myself on the back about my own brilliance. In the process of trying to make myself a little reminder dashboard plugin, so that weeks down the road when I can't figure out why my new site won't come up in the browser, and then remember that I have to add the new subdomain in hosts, I stumbled into a much larger issue, with more adventurous rabbit holes, that stoked the "maybe I really should get a Comp-Sci degree" fire, because then maybe I'd be able to understand what the heck happened. Continued in Refining my Process (Part 2).

Apr 16, 2014

Building a Browser Extension

I just finished cleaning up a relative's computer...again.  It seems nearly impossible; how can a computer that is barely ever used, and has had almost no software downloaded (almost!) be so corrupted with malware that it ceases to function?  I can solve this.

So many unwanted programs or unwanted newsletter subscriptions ride along with programs that are intentionally downloaded, just because the user neglects to uncheck the boxes before hitting the download button.  I'm convinced most people don't even see them there.  What if there was a browser setting that would remove default checked off boxes?  Sure would be nice.  Unfortunately, no such thing exists.  The Chrome extension store does offer a couple extensions that can uncheck or check all boxes on a given page, but it requires an intentional action on the part of the user, i.e. remembering to click the extension button.

Never having contemplated writing an extension before, I had no idea what the process might entail.  Surprisingly, Chrome extensions are mostly written in code I understand.  Depending on the purpose of the extension, you can supply CSS, HTML and/or Javascript.  While it took a little bit of experimenting to achieve the result I desired -- an unobtrusive script that ran on any form page without user input -- with a little help from a few websites, we were in business.

The Process

The first step was perfecting the script.  My script needed to identify that the page was a form, then go about removing any "checked" attributes that might exist* .  This is about as simple of a little JavaScript piece as they come.  I wrote a form with a few checkboxes and attached my script in the usual way, and tested to be sure I could still select the check box and send without any issues.  Once that was perfected, I removed the script and reset my form for testing when I installed the extension.

On to building the extension.  Chrome offers a very brief introduction to one type of extension.  While it is not exactly what I was interested in building it does introduce the most important, and most unfamiliar to me, piece of the extension puzzle, the manifest.json document.  This is the document that tells Chrome all about what you're building, where to locate the necessary files, and on which websites to run the extension.  Understanding the areas of this document is the key to building the type of extension you want and getting it to work.  Cory Gross has an excellent resource on Github that details aspects of these manifest settings.  Once you've decided what type of extension you are interested in building, you can start creating documents.

As intimidating as that sounds, this is actually the easiest step of all.  Alex Wolkov has written a tool that will build the extension's document structure, including inserting the default fields you need in the manifest.json document.  Each setting also includes a popup window on hovering over the (?) that offers a short explanation of the selection, and links to the Chrome developer page with more detailed instruction.  Upon downloading, open the manifest in a text editor and edit the fields.

In my example, I needed to edit only two documents, the manifest and the inject.js.  The trickiest bit was ensuring that my script would run on all web pages.  This setting falls under the content scripts->matches.  The tool automatically inserts a url to match all google pages, so editing that can be overlooked.  Google lists all the possible forms of match patterns for reference.  My script uses <all_urls>.

The next hurdle was placing the right section of code in the inject.js file.  The file is explicit about where the script should go.  Just strip the function call and drop in the actual script and it is all set.

Finally, create a set of icons to drop into the icon folder.  The icons are png files, so any image editor will do.  Create the largest size and then resize and save each smaller size.

Testing

Chrome makes it extremely easy to install an extension in development.  Navigate the settings -> tools -> extensions, just as you would install any extension.  At the top of the page is a checkbox to open the developer menu.  From there you can install an unpacked extension by navigating to your folder in which the extension lives.  On installation, Chrome will alert you to anything in the manifest that isn't formed correctly.  A little debugging and Google searching can help you fix those errors.

At this point, it's time to return to our test website we created when writing the script.  Be sure that you removed the link to the JavaScript file so that you can test the extension only.  It also may be helpful to disable any other extensions within the extension manager that you might be using because Chrome does not identify the extensions by name in the developer panels.  Using the Inspect Element tool (right click, Inspect Element), click the Sources tab and then the Content Scripts tab.  Reload the page if nothing shows up.  If still nothing appears, you need to return to the manifest.json and check that the matches section is properly formed to attach to the page as intended.

You should see a filename with a bunch of random letters.  If you've turned off all the other extensions, then you know this is your extension.  Opening the disclosure arrows will display files that make more sense.  If you are using an inject script as I have been, you will be able to navigate to the inject.js file and display your code (if creating another type of extension, the filename will be different, but you will still access it here).  You can debug this code, if necessary, just as you would debug any other JavaScript code in the browser.

Congratulations, you've built an extension!

Your extension can be installed and used as an unpacked extension with the files living locally on the computer.  It continues to function with the developer window in the extension manager closed, but may alert the user that a "possibly harmful" extension is installed every time the user opens the application.

Coming Soon...How to Publish your Extension.

*The actual script is beyond the scope of this piece, but I will update when the extension is available in the Chrome store for anyone interested.