Tag Archives: PHP

PHP: Easy Javascript compression with closure compiler

Here’s how to fairly easily compress/minify Javascript by using the Closure Compiler Service API.

More or less verbatim how I’m currently doing it over at bibelstudiet.no in my script controller class, and so far it’s been working great. Just remember to cache the result on your server so that you’re not calling the API more than necessary. In my case it’s handled further up the chain by the parent class 🙂

<?php
ob_start('ob_gzhandler');
header('Content-Type: text/javascript; charset=utf-8');

$files = ['foo.js', 'bar.js'];

$js = array_map('file_get_contents', $files);
$js = implode(PHP_EOL.PHP_EOL, $script);

$c = curl_init();
curl_setopt_array($ch, array
(
    CURLOPT_URL => 'https://closure-compiler.appspot.com/compile',
    CURLOPT_POST => TRUE,
    CURLOPT_POSTFIELDS => http_build_query([
        'language' => 'ECMASCRIPT5',
        'output_info' => 'compiled_code',
        'output_format' => 'text',
        'compilation_level' => 'SIMPLE_OPTIMIZATIONS',
        'js_code' => $js,
    ]),
));

if(curl_exec($ch) === FALSE)
    http_response_code(500) and exit("// ERROR: ".curl_error($c));

if(curl_getinfo($ch, CURLINFO_CONTENT_LENGTH_DOWNLOAD ) <= 1)
    echo $js;

curl_close($ch);

Note that if the compilation fails for any reason, the response will be empty. In that case I’ve chosen to output the original Javascript instead so the site doesn’t suddenly break. To check what went wrong, you need to repeat the request, but output_info set to errors instead of inline=”true”>compiled_code.

See their API documentation for more information about the parameters.

PHP: Array key whitelist and blacklist

Keep forgetting… writing it down so I can stop googling it…

function whitelist(array $array, array $whitelist)
{
    return array_intersect_key($array, array_flip($whitelist));
}

$filtered = whitelist($array, ['good1', 'good2', ... ]);
function blacklist(array $array, array $blacklist)
{
    return array_diff_key($array, array_flip($blacklist));
}

$filtered = blacklist($array, ['bad1', 'bad2', ...]);

PHP: Authorization header missing on Apache

I’m using a simple PHP cross-domain-proxy to be able to do some Javascript requests towards an API on a different domain. Worked great, until I needed to do basic authentication. I set the appropriate header to be passed through, 'Authorization': 'Basic ' + btoa(username+':'+password), but in the proxy script, that header had vanished.

Turns out it was Apache stripping it away. Don’t know if it’s because of security or because Apache thinks that, hey, I’m the one dealing with this stuff so no point sending it to the script. Anyways, seems you can get it back by doing the following in an .htaccess file:

RewriteEngine On
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]

Now the header is passed through to the API successfully and I’m no longer getting 401 Unauthorized back 🙂

Simple PHP proxy for cross origin HEAD requests

Update: Refactored this into a much more improved version, and you can find it on GitHub and Packagist.

Have some Javascript that runs through all the URLs on a site of mine to prep caching and check for dead links and other problems. Problem is that the site also includes embedded video files hosted by someone else. These fails of course because of cross origin restrictions and since I’m not in control of their servers I needed a workaround.

I wrote this small PHP script to work as a proxy and as far as I can see it works pretty great. Short and easy to follow as well, so that’s always fun 🙂

So basically the script just pipes through whatever headers it gets to the target URL and pipes back whatever headers it gets in the response. Seems to work, but let me know of weaknesses and easy improvements if you see any 🙂

<?php

$request_headers = getallheaders();
unset($request_headers['Cookie']);
unset($request_headers['Host']);

foreach($request_headers as $key => &$value)
    $value = $key.': '.$value;

$url = $_SERVER['QUERY_STRING'];
$limit = 20;

$curl = curl_init();
do
{
    curl_setopt_array($curl, array
    (
        CURLOPT_URL => $url,
        CURLOPT_HTTPHEADER => $request_headers,
       
        CURLOPT_RETURNTRANSFER => TRUE,
        CURLOPT_HEADER => TRUE,
        CURLOPT_NOBODY => TRUE,

        CURLOPT_FOLLOWLOCATION => TRUE,
        CURLOPT_MAXREDIRS => $limit--,
    ));

    ob_start();
    $headers = trim(curl_exec($curl));
    $url = curl_getinfo($curl, CURLINFO_REDIRECT_URL);
    ob_end_clean();
}
while($url and $limit > 0);

curl_close($curl);

$headers = trim(substr($headers, strrpos($headers, "\r\n\r\n")));
header_remove();
foreach(explode("\r\n", $headers) as $h)
    header($h);

Notes

  • The Cookie and Host headers sent from the browser are removed so they don’t mess up the request.
  • CURL wasn’t acting properly where I deployed this. It didn’t follow redirects, and curl_exec output content to the browser even with return transfer set to true. So it has a manual workaround for following the redirects and uses output buffering to make sure nothing goes to the browser before we want to.

PHP: Simple directory recursion

Keep running into scenarios where I need to scan through a file system and it’s actually pretty simple if you just know what classes to use. So… note to self and others:

// This should return false if there is something you want excluded
function filter($file, $key, $iterator)
{
    $exclude = array('.git');
    return ! in_array($file->getFilename(), $exclude);
}

// Recursive directory iterator for current directory, ignoring dots
$it = new RecursiveDirectoryIterator('.', FilesystemIterator::SKIP_DOTS);
// Wrapped by a filtering iterator with our filter function
$it = new RecursiveCallbackFilterIterator($it, 'filter');
// Wrapped by an iterator which automatically traverses children for us
$it = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::SELF_FIRST);

// And then just loop :)
foreach($it as $file)
{
    echo str_repeat("\t", $it->getDepth())
        . $file->getRealPath()
        . PHP_EOL;
}

This skips the annoying dots, properly excludes directories you don’t want and pretty much works the way it should.

Order WordPress RSS feed by modified rather than published

Adding the following to the functions.php of your theme should make the posts in your WordPress RSS feed sort by when the post was last modified rather than when it was published. Useful in some cases when you for example want to push out updated posts as well.

function wpse49312_alter_the_query( $request )
{
    $dummy_query = new WP_Query();
    $dummy_query->parse_query($request);

    if($dummy_query->is_feed())
        $request['orderby'] = 'modified';

    return $request;
}
add_filter('request', 'wpse49312_alter_the_query');