google-prettify

Friday, September 27, 2013

Call a console command from a controller (Symfony2)

The following code snippet shows how you can call a console command from your controller:

<?php

namespace Acme\DemoBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\RedirectResponse;

// these import the "@Route" and "@Template" annotations
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;

use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Component\Console\Input\StringInput;
use Symfony\Component\Console\Output\StreamOutput;

class DemoController extends Controller
{
    /**
     * @Route("/command-runner/", name="_command_runner")
     * @Template()
     */
    public function command_runnerAction()
    {
        $kernel = $this->container->get('kernel');
        $app = new Application($kernel);

        $input = new StringInput('router:debug');
        $output = new StreamOutput(fopen('php://temp', 'w'));

        $app->doRun($input, $output);

        rewind($output->getStream());
        $response =  stream_get_contents($output->getStream());    
        
        return array('response' => $response);
    }
}

The above snippet will return the output of the command run (in this case "router:debug") in the response variable, which can be rendered into the your views.

You can provide any other commands and additional options by simply making changes to the string provided to the StringInput object, eg. StringInput('cache:clear --env=prod');

This snippet was tested on Symfony2 Framework version 2.3.

Sunday, September 22, 2013

Limiting Wordpress memory usage when doing a bulk insert of Wordpress

Sometimes you need to bulk import lots of posts from different sources into Wordpress. This is quite a simple process using the Wordpress API:

<?php

ini_set('memory_limit','600M');

require_once('../../../wp-load.php');

$count = 1;

$to_add = 50000;

echo "Adding $to_add posts..." . PHP_EOL;

while(true) {
    if($count>$to_add)
        break;
    
    // Create post object
    $my_post = array(
      'post_title'    => 'My post ' . $count,
      'post_content'  => 'This is my post.',
      'post_status'   => 'publish',
      'post_author'   => 1,
      'post_category' => array(8,39)
    );
    
    // Insert the post into the database
    wp_insert_post( $my_post );
    
    $count++;
}

echo "Done." . PHP_EOL;

echo "Peak memory used (MB): ". memory_get_peak_usage() / (1024*1024)  . PHP_EOL;

?>

The above example works well for a small number of posts (somewhere around 10,000 posts); however when you have to import a larger number of posts, the above code ends up taking alot of memory, and can cause your server to run out of memory. For example, the above code (50,000 posts added) took up 209 MB of memory when importing into a new instance of Wordpress (no plugins).

Depending on which plugins you have enabled the amount of memory the above script takes can vary considerably. Running the above script with lots of other plugins could cause it to take even more that 209 MB.

One thing you can do to make the above script use less memory is to turn off the Wordpress cache. This can be done by calling the "wp_suspend_cache_addition" function:

<?php
ini_set('memory_limit','600M');

require_once('../../../wp-load.php');

wp_suspend_cache_addition(true);

$count = 1;
$to_add = 50000;
echo "Adding $to_add posts..." . PHP_EOL;

while(true) {
    if($count>$to_add)
        break;
    
    // Create post object
    $my_post = array(
      'post_title'    => 'My post ' . $count,
      'post_content'  => 'This is my post.',
      'post_status'   => 'publish',
      'post_author'   => 1,
      'post_category' => array(8,39)
    );
    
    // Insert the post into the database
    wp_insert_post( $my_post );
    
    $count++;
}

echo "Done." . PHP_EOL;

echo "Peak memory used (MB): ". memory_get_peak_usage() / (1024*1024)  . PHP_EOL;

?>

After the addtion of the "wp_suspend_cache_addition" function the above script - adding 50,000 posts takes up only 14 MB - thats a reduction of 93%.

The above script was tested on Wordpress 3.6.1.

Tuesday, August 6, 2013

Deploying websites using Git & Assembla

If you are hosting your website on a server to which you have SSH access, you can use Git to deploy changes to it.

Broadly speaking, the basic process is very simple - the server gets the code from the Git repository and then syncs it with the website. However there are a few issues worth considering when you implement this solution.

User Accounts

As we will be using Git over SSH, one thing that we will need to do is setup SSH keys between the Assembla Git repository and the server we will be deploying to - ie. make sure that the server can access the Git repository hosted on Assembla.

Here two 'user accounts' come into play - the Assembla user and the user on the server.

For deployment purposes rather than using an existing Assembla user's account, it is advantageous to use a special "deployment account". This ensures that the deployment process is not tied any particular user - who may or may not be part of the project down the line.

The other account that is on the server, is the one whose public key will be uploaded to Assembla and given access to the repository. You need to make sure that it has the necessary permissions and rights to do the deployment.

Setting up SSH keys

First thing you need to do is to login to the server with the user that you are going to be performing the deploy with; and get it's public SSH key, which should be present at ~/.ssh/id_rsa.pub OR ~/.ssh/id_dsa.pub. If it isn't you can generate one by using the following command:

ssh-keygen -t rsa -C "email@example.com"

Once you have the key file generated, open it using and copy all it's contents to your clipboard.

Now login to Assembla using your "deployment user", and upload the key.

Goto Profile > Manage SSH Keys > "Add a key, pasting it from clipboard."

Assembla profile page

Once the key is added you can also set this key to "Read-only Mode" here, as we are not expecting to make any commits using from this account.

Confirm the key is working by trying to do a clone (you will need to confirm the identity of the server).

Script to deploy

Now that we can access the git repository directly, a simple bash script will do the job of deploying the website:

mkdir -p ~/repos #make a "repos" directory where we will get the Git repository

cd ~/repos 

git clone <repo address goes here> # clone the repo (if required), if a repo is already there it will throw an error and go on

git pull #pull all the latest changes

git checkout master # checkout the branch you want to deploy from

rsync -avz ~/repos/src ~/htdocs/ # update the website

The above script is a rudimentry example, you can make alterations and additions as required.

If there is any other processes that you need to perform after a deploy, such as sending emails, clearing cache etc., they can easily be added in this script.

Sunday, July 28, 2013

Making Wordpress's search form submit to a 'friendly' URL

In Wordpress, you can customize how URLs are structured, via the permalinks page.

So, for example posts that looked like

http://example.com/?p=1

can be configured to look like

http://example.com/hello-world/

The second URL is obviously easier to read, more aesthetically pleasing and of course, more SEO friendly, as now the URL itself is giving us a hint about the content of the page.

This is done simply making some updates in the permalinks portion of the wp-admin page.

Wordpress 5.2's permalinks page.
While this works great for posts, you will notice that this does not extend to the search form, which by default still submits using a query string:

http://example.com/?s=hello

Interestingly, you will find that after you have changed your permalink setting, a URL of the format /search/{search term} does exist, so if you enter:

http://example.com/search/hello

you will be taken to the search page.

However, a simple HTML form can't submit to this friendly search URL, as the URL itself contains the search term. (A the form's action attribute will need a complete URL, including the search term - but we can't know the search term when defining the form).

The most straight forward workaround for this is add a redirect in Wordpress to make sure the '?s=hello' search page is redirected to '/search/hello' instead. An example this can be found here: http://wpengineer.com/2258/change-the-search-url-of-wordpress/

Another option is to use Javascript and change the form's action attribute just before submitting the form to the server.

Here is the code:

<script type="text/javascript">
    function doSearchSubmit(searchForm) {
        
        //get the search form's input field
        var s = jQuery(searchForm).find('#s'); 
        
        //change the form's action attribute to include the search term
        searchForm.action='<?php bloginfo('url'); ?>/search/'+s.val(); 
        
        //disable the form's input field so that it is not submitted with the form
        s.attr('disabled', 'disabled');
        
        return true;        
    }
</script>

<form role="search" method="get" id="searchform" action="<?php bloginfo('url'); ?>" onsubmit="return doSearchSubmit(this);"> 
 <div><label class="screen-reader-text" for="s"><?php _e('Search for:'); ?></label> 
 <input type="text" value="" name="s" id="s" /> 
 <input type="submit" id="searchsubmit" value="<?php _e('Search') ?>" /> 
 </div> 
</form>

The above code goes in 'searchform.php' which should be at the root of your theme. If there isn't one there already, you can add one.

It's pretty simple - instead of submitted the from directly, we use some Javascript to change the action attribute of the from to the friendly URL instead.

This works as expected however there is one minute issue I noticed while testing on Chrome: when you submit this form the URL it goes to looks like this:

http://example.com/search/hello?

(This doesn't happen on Firefox 22.0 or IE 9).

To overcome this issue on Chrome, we can set the form method attribute to 'post' instead of 'get' - this will ensure no query string remnants are seen on any browser.

Another thing we could consider is to never have the form submit at all - instead we just change the location of the page to go directly to the friendly search URL:

<script type="text/javascript">
 function doSearchSubmit(searchForm) {

        //get the search form's input field
        var s = jQuery(searchForm).find('#s');         
        
        //just redirect to the search page
        window.location='<?php bloginfo('url'); ?>/search/'+s.val(); 
        
        return false;
    }
</script>

<form role="search" method="get" id="searchform" action="<?php bloginfo('url'); ?>" onsubmit="return doSearchSubmit(this);"> 
 <div><label class="screen-reader-text" for="s"><?php _e('Search for:'); ?></label> 
 <input type="text" value="" name="s" id="s" /> 
 <input type="submit" id="searchsubmit" value="<?php _e('Search') ?>" /> 
 </div> 
</form>
 

Friday, July 19, 2013

Styling the 'pre' tag in Blogger's 'Dynamic Views' template

If you are using Blogger's Dynamic Views template, and are also using the 'pre' tag in your posts, you'll notice that the content enclosed in your pre tags will not be showing as expected.

Below is an example:

No appropritate styles added to the 'pre' tag by default.
This is a simple CSS fix. To add the CSS goto the 'Template' page in your blogger admin area, and click on the 'Customize' button.

From there click on 'Advanced' then on 'Add Css'.

Dynamic styles customization area.

Add the following custom CSS:

pre {
  display: block;
  padding: 9.5px;
  margin: 0 0 10px;
  font-size: 13px;
  line-height: 20px;
  word-break: break-all;
  word-wrap: break-word;
  white-space: pre;
  white-space: pre-wrap;
  background-color: #f5f5f5;
  border: 1px solid #ccc;
  border: 1px solid rgba(0, 0, 0, 0.15);
  -webkit-border-radius: 4px;
     -moz-border-radius: 4px;
          border-radius: 4px;
}

(The above CSS is taken from Twitter Bootstrap, http://twitter.github.io/bootstrap/)

Finally click on 'Apply to Blog' (button in top right corner).

Saturday, July 13, 2013

Creating animated GIFs of videos using free tools

A small step by step tutorial explaining how to make animated GIFs of videos using free software.

 
Note: Tutorial was made on Windows, though the same steps could be followed for Linux as the tools being used to make the gif are cross platform.

Aquire Software

First of all get the software that you will be needing. For this tutorial we need two separate tools:

1) ffmpeg (http://ffmpeg.org/)
2) ImageMagick (http://www.imagemagick.org)

ffmpeg - this is a really powerful software library that deals with audio/video. We will be using it to extract frames from a video.

ImageMagick - another very powerful software library, this one deals with images. We will of course primarily be using it to combine the frames into a gif.

Extract Frames

To extract frames using ffmpeg, we will be using the following command:
 
.\ffmpeg\ffmpeg.exe -ss $startSeconds -i "$sourceFile" -r $frameRate -t $duration $outputDir\frame%04d.bmp 
 
Arguments are as follows:
 
$startSeconds - specifies how many seconds into the video frames should start to be extracted.
$sourceFile - video whose frames need to be extracted.
$frameRate - rate at which frame should be extracted. Rate close to video's native frame rate = smoother animation, but larger gif; Lower rate = jerky animation, but smaller gif.
$duration - specifies how many seconds worth of video do you want to extract frames for.
$outputDir - where the extracted frames should be placed.
 
The above command will output bmp files (in theory this should maintain the highest quality+be the fastest).
 
A real world example:
 
.\ffmpeg\ffmpeg.exe -ss 957 -i "N:\video\tv\The Simpsons - The Complete Seventh Season\The Simpsons - S07E02 - Radioactive Man.avi" -r 24 -t 8 "N:\tmp\frame%04d.bmp"
 
In the above example we start extracting frames from video "The Simpsons - S07E02 - Radioactive Man.avi" at 00:15:57 (fifteen minutes, 57 seconds). (In seconds this is of course 15x60+57 = 957). Frame rate is 24, and we extract 8 seconds worth of frames from the movie. The output is put into the N:\tmp folder, with the files prefixed with 'frame'.
 
After the command is complete we can see the frames extracted in the folder:
 
Folder showing the extracted frames.
As expected we have 192 frames extracted here, as 8 (duration) x 24 (frame rate) = 192 frames.

Resizing The Images (optional)

We could make the gif directly out of the extracted frames, however we will want to re-size them a bit to make the output gif smaller (as it's going to be animated the size will be larger than average image, so we would like to shave off as much of the size as possible).

To do this we are going to be using the following ImageMagick command:
 
.\image-magick\mogrify -resize $resizePercentage $outputDir\*.bmp
 
Arguments are as follows:
 
$resizePercentage - how much bigger or how much smaller you want to make the images. eg. Speficing 80% here will make the image 20% smaller.
$outputDir - the folder where the images that will be re sized are to be found. (*.bmp means all bitmap images in the folder will be re sized).
 
Real world example:
 
.\image-magick\mogrify -resize 50% "N:\tmp\*.bmp"
 
Here we are making the images half their original size.
 
Make The Animated Gif
 
Now for the final step, which is combining the images into an animated gif.
 
For this we the following ImageMagick command:
 
.\image-magick\convert.exe -delay $delay -loop 0 "$outputDir\*.bmp" "$gifFileName.gif"
 
Arguments are as follows:
 
$delay - The gif's frame rate. Should be specified as 1x24 or 1x16. (1x24 = 24 frames per second, 1x16 = 16 frames per second etc). 1x16 appears to be the best value considering some browsers cap GIF frame rates.
$outputDir - This is where we have our frames extracted, in this case all bitmap files in outputDir will be added to the gif.
$gifFileName - The name of the gif file that will be generated.
 
Real world example:
 
.\image-magick\convert.exe -delay 1x16 -loop 0 "N:\tmp\*.bmp" "N:\simpsons.gif"
 
And that's it, after the above command completes, you should have your animated gif.
 
Here is the one we created for this tutorial:
 
The final output.
 
Well that's it, hope you found the tutorial useful.
 
I will be creating a powershell script to automate these steps, will share it when it's ready.