PHP

wkhtmltopdf repeat on subsequent pages

wkhtmltopdf has a bug as a result of a webkit bug. This means that the nice css styles for table printing don’t work in wkhtmltopdf.

Fortunately for us, wkhtmltopdf can handle JavaScript and that enables us to modify the DOM nicely prior to PDF creation.

Add the class ‘split_this_table’ to the table(s) you need to sort out over the page break, and then insert this code into the page in question:

$('.split_this_table').each(function(index, element) {

    //the height available is dependant on another item on the page
    var expanded_line = $('#another_element').size().height / 5;

    //manual calculation of the header size
    var per_page = 20 - expanded_line;

    //how many pages of rows have we got?
    var pages = Math.ceil($('tbody tr').length / per_page);

    //if we only have one page no more
    if (pages == 1) {
        return;
    }

    //get the table we're splutting
    var table_to_split = $(element);
    var current_page   = 1;

    //loop through each of our pages
    for (current_page = 1; current_page <= pages; current_page++) {

        //make a new copy of the table
        var cloned_table = table_to_split.clone();

        //remove rows on later pages
        $('tbody tr', table_to_split).each(function(loop, row_element) {

            //if we've reached our max
            if (loop >= per_page) {

                //get rid of the row
                $(row_element).remove();
            }
        });

        //loop through the other copy
        $('tbody tr', cloned_table).each(function(loop, row_element) {

            //if we are before our current page
            if (loop < per_page) {

                //remove that one
                $(row_element).remove();
            }
        });

        //insert the other table afdter the copy
        if (current_page < pages) {

            //insert the new table
            cloned_table.insertAfter(table_to_split);
        }

        //make a break
        cloned_table.css('page-break-before', 'always');

        //reset the table to the copy
        table_to_split = cloned_table;
    }
});

Mounting HTML folder in Centos VirtualBox

I have a particular Linux set up I need to test something on, but I use a Mac, so I use VirtualBox with a Linux VM for the testing.

So, to do this normally, you either install an IDE on the VM and code on there. Installing Java, Netbeans, Subversion, Git, etc, etc, etc, or, you just checkout the code on the VM and make code changes on the Mac…

Neither of these options are really that great, so a friend recommended I mount the code folder from the Mac on the Linux VM. Great idea. So I install a new copy of CentOS and keep it minimal, no window managers, nothing like that. Just Apache, and the database connectors I require.

Now, I would not class myself as a Linux expert in any shape or form. I can set up a server and manage it, ut if you delve too deeply, I start to struggle. I used the VirtualBox automatic mounting for my code folder (using Guest Additions) – this just would not work. I tried checking out the code into a local folder and that worked fine. Must be a problem with the share/permissions or something.

After wasting an hour or so checking permissions and groups, I gave up and tried the internet. Came across a really helpful post, which I sort of followed. I had to alter it for CentOS as it was Ubuntu orientated.

You have to install Guest Additions first!

Add a virtual box shared folder

Create a Transient folder in the shared folders section and take note of the name, I used ‘sites’ – do not select any of the checkboxes when creating the share. This is what causes the problem as VirtualBox creates the share with permissions that Apache cannot use.

mkdir /var/www/sites
mount -t vboxsf -o rw,uid=0,gid=0 sites /var/www/sites

I used the UID and GID of 0 as I was only installing this VM as root. There were no other users installed, but you do need to change the UID and GID of the Apache process (www-data?)

Test that and make sure it works, if it does, lets make it permanent:

nano /etc/fstab
sites /var/www/sites vboxsf defaults 0 0

Hey presto, the folder is mounted on boot and you should be able to serve the docs from there.

Obviously you need to update the vhosts to point at the shared folder. But you know how to do that, right?

PHP exec() not returning output

I found that a script I was running was calling some linux functions using exec() but they weren’t always successful and I couldn’t tell why.

exec('command to run');

This would fail silently

$result = exec('command to run 2>&1', $output);

This would correctly send me back the result (in $result) and then I could do whatever with the error(s)

Apache PHP mkdir not writable?

If you ever find that you are creating a folder with PHP, and its immediately not writeable by Apache, then you’ve probably done what I did with the chmod. It needs to be an octal value, and PHP will not assume it is. So you have to prefix with a zero.

mkdir("/path/to/folder/structure/", 777, true);

Should actually be:

mkdir("/path/to/folder/structure/", 0777, true);

Took me a while to work it out, I thought it was something to do with Mac permissions…

Add a path to the PHP include path

I recently wanted to add a Zend library to a project without adding the entire framework.

I found that internally, the Zend application requires the Library path to be in the include, as it uses relative includes. So, easy to fix without editing the actual pages. I just needed to add the folder they were in, to the PHP include path.

function add_path_to_include ($path)
{
    //get the existing paths using the PATH_SEPERATOR constant
    $paths = explode(PATH_SEPARATOR, get_include_path());

    //if the new path isn't already there
    if (array_search($path, $paths) === false) {

        //add it on
        array_push($paths, $path);
    }

    //add them all back on
    set_include_path(implode(PATH_SEPARATOR, $paths));
    }

Jobs a goodun…

Errors trying to access Google IMAP through PHP

imap_open() [function.imap-open]: Couldn't open stream {imap.gmail.com:993/imap/ssl}INBOX

This error /can/ be missleading. I thought something was up with the stream (guessing there was a misconfiguration with PHP, IMAP and openSSL) – but it turned out I had typed the wrong password in the initial request.

Just incase anyone else is struggling here, just check that first.

Then, ensure you have installed the openSSL and the php5-imap extension correctly.

AllowEncodedSlashes not taking effect?

If you are switching on the AllowEncodedSlashes setting in the apache conf file, and it doesn’t seem to be making any difference, then it may well be because you are using vhosts, and the setting is not automatically propergated through them.

You’ll need to edit the vhost and specify the setting within the config part of the vhost:

<VirtualHost *:80>
    ServerName mytest.local
    DocumentRoot /var/www/site2/
    AllowEncodedSlashes On
</directory>

Be sure to read all about it, and understand the security risks.