Check whether URL match with Wildcard pattern

Suppose, you have some rules to check whitelisted url. So everytime whenever you will get a new url so you can cross match that URL with your whitelisted URL. And whitelisted URLs sometimes can be wildcard url. So to check whether the given URL matched any of the wildcard urls.

<?php
$whiteListedUrls = [
    "https://google.com/test/*",
    "https://yahoo.com/test/index.html",
    "https://sohelrana.me/*",
    "https://sohelrana.me"
];

$url = "https://google.com/test/testWildCard/ok.html";


function checkUrlWildcard($url, $whiteListUrls = [])
{
    foreach ($whiteListUrls as $wUrl) {
        $pattern = preg_quote($wUrl, '/');
        $pattern = str_replace('\*', '.*', $pattern);
        $matched = preg_match('/^' . $pattern . '$/i', $url);
        if ($matched > 0) {
            return true;
        }
    }

    return false;
}

//it will return true
var_export(checkUrlWildcard($url, $whiteListedUrls));

https://google.com/test/* this url means actually all url path after https://google.com/test/. So if we want to check https://google.com/test/testWildCard/ok.html whether it is covered with our rules or not. So it will return true of course.

It’s a simple PHP script. But may help somebody.

Copy BigQuery dataset to another dataset – copy all tables at once

Sometime it’s necessary to copy or clone the entire Big Query dataset to another dataset. If you Big Query dataset has lots of table, then it’s very time consuming to clone or copy all tables one by one.

But for the help of Shell script, we can combine few `bq`  command and can make our life easier for this types of bulk tasks. I just googled to get similar solutions and combined few things in a single shell script.

Here is the script to copy or clone the entire Big Query dataset in another dataset.

Shell Script to copy Big Query Dataset

#!/bin/sh
export SOURCE_DATASET="BQPROJECTID:BQSOURCEDATASET"
export DEST_PREFIX="TARGETBQPROJECTID:TARGETBQDATASET._YOUR_PREFIX"
for f in `bq ls -n TOTAL_NUMBER_OF_TABLES $SOURCE_DATASET |grep TABLE | awk '{print $1}'`
do
  export CLONE_CMD="bq --nosync cp $SOURCE_DATASET.$f $DEST_PREFIX$f"
  echo $CLONE_CMD
  echo `$CLONE_CMD`
done

In the above command –nosync will help you to load bq job asynchronously. So you don’t need to wait for current job to finish. Also TOTAL_NUMBER_OF_TABLES you need to replace with existing dataset’s total number of tables you want to copy. i.e: 200

Now, run the above shell script and start kicking the bq job payload.

Supercharge WP REST API with Google App Engine

It seems that I am pretty late here to play with WordPress REST API. It’s really super cool! Now I can think about how well and fast I can distribute or work with wordpress blog posts. Even now you can host your whole WordPress inside a static HTML page. Funny? Yea, like your HTML page will interact with your REST API json response and small JS can help you to display inside page. Then you will get 10000000x super fast blog post delivery. Trust me! It works. You will understand if you are a little techie guy.

I was thinking about if I can easily get all of my posts’s data as REST API Json response then easily I can use them wherever and whenever I want. But there must be a trick. Cause still this REST API is working from inside your main WP hosting.

But what if (IF) we can recruit some middleman who can hold data and deliver those data without even interacting with your original WordPress site. So you will save lots of money and your site’s performance will be super boosted.

I just run an experiment (I shared my experimented snippet here) with Google App Engine. Why Google App Engine? Ask that to google yourself. Google App Engine is the best solutions for ready-set-go types of app deployment with lots of features that Google maintains themselves. So I am going to write a small PHP code which will load your site’s REST API JSON data and after that rest of the request it will server from directly GAE memcache. So, more easily, if your site has 1M audience a day, then most probably you will hit your original WP site once, and 999999 user will get that data from directly App Engine (PHP app data persistent through memcache).

I just tried it and it works and I tried to do 50,000 hits and it just took few milliseconds to deliver me my wordpress site’s data from Google App Engine and I just designed a HTML page with simple JS that will load the content from my App Engine and will display inside HTML page, and you know HTML page you can serve billions user in a minute. Voila 🙂

So here is my little PHP script and also I uploaded the full GAE implementation in a GitHub repository so you can directly download, change your site’s URL and deploy to Google App Engine.

<?php
/**
 * Serve remote URL content through App Engine by using Memcache. Pretty interesting.
 * It's really cool!
 *
 * @Author Shaharia Azam <shaharia@previewtechs.com>
 */
define("KB_JSON_URL", "https://YOUR-WEBSITE-ADDRESS/wp-json/wp/v2");

$memcached = new Memcached();
$memcached->addServers([
    ['localhost', 11211, 33]
]);

/**
 * @param $url
 * @param string $method
 * @return mixed
 */
function fetchJSONFromRemoteWP($url, $method = 'GET')
{
    $curl = curl_init();
    curl_setopt_array($curl, array(
        CURLOPT_URL => $url,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_MAXREDIRS => 2,
        CURLOPT_TIMEOUT => 30,
        CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
        CURLOPT_CUSTOMREQUEST => $method,
        CURLOPT_HTTPHEADER => [],
    ));

    $data = curl_exec($curl);
    curl_error($curl);
    curl_close($curl);

    return $data;
}

$remoteUrl = KB_JSON_URL . $_SERVER['REQUEST_URI'];

$cacheKey = base64_encode($remoteUrl);

$content = $memcached->get($cacheKey);
if (!empty($content)) {
    $data = $content;
} else {
    $data = fetchJSONFromRemoteWP($remoteUrl);
    $memcached->set($cacheKey, $data, 360000);
}

header('Content-Type: application/json');
echo json_encode(json_decode($data, true));

exit;

And here is the app.yaml configuration for Google App Engine

runtime: php55
api_version: 1

service: kb-wp-reverse-proxy

threadsafe: true

handlers:
- url: /assets
  static_dir: public/assets

- url: /*
  script: public/index.php
  secure: always

- url: /.*
  script: public/index.php
  secure: always

skip_files:
- ^.git$

This snippets are available on GitHub. If you face any trouble and want to optimize your site and make it super-fast and stable with this types of solutions, reach me anytime at shaharia@previewtechs.com

GeoIP alternative to get IP location – Google App Engine PHP Recipes

Today’s recipes is all about to get very basic information about your visitor’s IP address location. Unfortunately, in Google App Engine, PHP GeoIP extension is not enabled in their standard environment. So sometimes, it’s essential for application developer to get the visitor’s IP address location.

Here, you can easily get user’s IP address location with 3 information easily and by default from Google App Engine. In GAE, if you will discover that Google app engine itself added few extra _X_headers in $_SERVER super-global variable. I am dumping the $_SERVER variable here.

<?php
//Output of $_SERVER

/*[
    'APPLICATION_ID' => 'YOUR GAE APPLICATION ID',
    'AUTH_DOMAIN' => 'gmail.com',
    'CURRENT_MODULE_ID' => 'default',
    'CURRENT_VERSION_ID' => '20170319t185047.399949465273621812',
    'DEFAULT_VERSION_HOSTNAME' => 'xxxxxxxxxx.appspot.com',
    'DOCUMENT_ROOT' => '/base/data/home/apps/xxxxxxxxxxxxxx/20170319t185047.399949465273621812',
    'HTTPS' => 'on',
    'HTTP_ACCEPT' => 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*\/*;q=0.8',
    'HTTP_ACCEPT_LANGUAGE' => 'en-US,en;q=0.8,bn;q=0.6,ms;q=0.4,pt;q=0.2',
    'HTTP_HOST' => 'xxxxxxxxxx.appspot.com',
    'HTTP_UPGRADE_INSECURE_REQUESTS' => '1',
    'HTTP_USER_AGENT' => 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.110 Safari/537.36',
    'HTTP_X_APPENGINE_CITY' => 'dhaka',
    'HTTP_X_APPENGINE_CITYLATLONG' => '23.709921,90.407143',
    'HTTP_X_APPENGINE_COUNTRY' => 'BD',
    'HTTP_X_APPENGINE_REGION' => '?',
    'HTTP_X_CLOUD_TRACE_CONTEXT' => 'xxxxxxxxxxxxxxxxxxxxxxxxxx/xxxxxxxxxx;o=x',
    'INSTANCE_ID' => 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
    'PATH_TRANSLATED' => '/base/data/home/apps/xxxxxxxxxxxxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxxx/index.php',
    'PHP_INI_SCAN_DIR' => '/base/data/home/apps/xxxxxxxxxxxxxxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxxx/',
    'PHP_SELF' => '/index.php',
    'REMOTE_ADDR' => 'xxx.xxx.xxx.xxx',
    'REQUEST_ID_HASH' => 'XXXXXXXX',
    'REQUEST_LOG_ID' => 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
    'REQUEST_METHOD' => 'GET',
    'REQUEST_URI' => '/',
    'SCRIPT_FILENAME' => '/base/data/home/apps/xxxxxxxxxxxxxxxxxxxxxx/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/index.php',
    'SCRIPT_NAME' => '/index.php',
    'SERVER_NAME' => 'xxxxxxxxxxxxxxxxxxx.appspot.com',
    'SERVER_PROTOCOL' => 'HTTP/1.1',
    'SERVER_SOFTWARE' => 'Google App Engine/1.9.48',
    'USER_IS_ADMIN' => '0',
    'REQUEST_TIME_FLOAT' => 148992.7,
    'REQUEST_TIME' => 14899,
    'argv' =>
        array(),
    'argc' => 0,
];*/


//Get the visitor's IP details
$visitorIp = [
    'ip' => $_SERVER['REMOTE_ADDR'],
    'HTTP_X_APPENGINE_CITY' => $_SERVER['HTTP_X_APPENGINE_CITY'] ?: null,
    'HTTP_X_APPENGINE_CITYLATLONG' => $_SERVER['HTTP_X_APPENGINE_CITYLATLONG'] ?: null,
    'HTTP_X_APPENGINE_COUNTRY' => $_SERVER['HTTP_X_APPENGINE_COUNTRY'] ?: null,
    'HTTP_X_APPENGINE_REGION' => $_SERVER['HTTP_X_APPENGINE_REGION'] ?: null
];

 

And from that, we can easily get the visitor’s City, City-level lat long, country and region that primary will help you to get visitor’s location.

Slim PHP Framework PhpStorm IDE autocompletion Solution

I am a big fan of PHP Slim Framework. But sometimes, I realized that when I work with large and complex libraries with Slim as dependency. It just kills my productivity, it kills my valuable time too. It’s all because of I can’t remember all the method names, properties of my dependent class or libraries. And with Pimple dependencies Slim Framework don’t have any way to bypass referencing of my third party libraries which I add through it’s container as dependency. So I decided to figure out a solution for me.

First, I just installed and configured slim framework and here is my scripts.

<?php
//index.php
require "../vendor/autoload.php";
$app = new \Slim\App();
$container = $app->getContainer();

/**
 * @return \ShahariaAzam\Classes\HintsClass
 */
$container['hints'] = function () {
 return new \ShahariaAzam\Classes\HintsClass();
};

$app->get('/foo', function (\Slim\Http\Request $request, \Slim\Http\Response $response) {
 /** @var Dummy $this */
 $this->hints->printHelloWorld();
 $response->write("Hello World");
});

$app->get('/another-foo', function (\Slim\Http\Request $request, \Slim\Http\Response $response) {
 /** @var Dummy $this */
 $this->hints->printHelloWorld();
});
$app->run();

 

And I created a class HintsClass. Now the main trick is, I created a dummy _ide_autocomplete.php file in the project root and defined all the containers key as public property. Like this.

<?php
//src/HintsClass
namespace ShahariaAzam\Classes;

/**
 * Class HintsClass
 * @package ShahariaAzam\Classes
 */
class HintsClass
{
    /**
     * @var int
     */
    public $test = 1;

    /**
     * @return bool
     */
    public function testMethod()
    {
        return true;
    }

    /**
     * @return string
     */
    public function printHelloWorld()
    {
        return "HelloWorld";
    }
}

 

Now our goal is from inside route, our PHPStorm IDE will show the autocomplete and hinting for code completion when we will access this class with $this->hints->[ctrl+space to see autocompletion]. And in our _ide_autocomplete.php file we wrote the following codes. FYI, this _ide_autocomplete.php will never execute. It just used for giving IDE as a referential hinting for all the properties .

<?php

//_ide_autocomplete.php
class Dummy
{
    /**
     * @var \ShahariaAzam\Classes\HintsClass
     */
    public $hints;
}

 

You will see in this Dummy class file according to our slim containers[‘hints’], I just mentioned the same return reference here. And see my main index.php, in every route I just gave IDE hints about the $this context with

/** @var Dummy $this */

And after that from route context IDE will show the autocompletion of our dependencies like $this->hints[ctrl+space to see suggestions].

You can see my whole scripts are in GitHub https://github.com/shahariaazam/slim-phpstorm-autocomplete. And see this work in YouTube, https://www.youtube.com/watch?v=jyEvApLRofw .Please let me know if any issue found, write me in comments. Thank you.