Name | Link | Description |
---|---|---|
was.php | was.php | General Purpose Library |
The following snippets, adapted from Greg Schechter's MSN Blog can be used to convert between Latitude and Longitude and mercator coordinates. This can be used with a mercator projection map such as the following map:
The function wasGeoToMercatorPoint
takes as input:
0
if using the whole map of the world)0
if using the whole map of the world)and returns an array containing the map coordinate.
function wasGeoToMercatorPoint($latitude, $longitude, $mapWidth, $mapHeight, $mapLeft=0, $mapTop=0) { $x = $mapLeft + ($longitude + 180) * $mapWidth / 360; $y = $mapTop + ($mapHeight/2) * (1-(log(tan(deg2rad($latitude)/2 + M_PI/4))) / M_PI); return array($x, $y); }
The function wasGeoToMercatorPoint
takes as input:
x
- pixel locationy
- pixel location0
if using the whole map of the world)0
if using the whole map of the world)and returns the latitude and longitude corresponding to the pixel on the map.
function wasMercatorPointToGeo($x, $y, $mapWidth, $mapHeight, $mapLeft=0, $mapTop=0) { $f = (($x-$mapLeft) * 360 / $mapWidth) - 180; $l = rad2deg (2 * atan ( exp ( M_PI * (1 - 2 * ($y-$mapTop)/$mapHeight ) ) ) - M_PI/2); return array($l, $f); }
The variable:
$_SERVER['REMOTE_ADDR']
contains the address that the client connects from.
The variable:
$_SERVER['HTTP_X_FORWARDED_FOR']
contains the IP, if the client is using a proxy server.
The variable:
$_SERVER['SERVER_ADDR']
contains the IP address that the server is listening on.
Filter the array through the built-in strlen
function:
$clean_array = array_filter($dirty_array, 'strlen');
$clean_array = array_values($dirty_array);
#colin.mollenhour.com function json_decode_nice($json, $assoc = FALSE){ $json = str_replace(array("\n","\r"),"",$json); $json = preg_replace('/([{,]+)(\s*)([^"]+?)\s*:/','$1"$3":',$json); return json_decode($json,$assoc); }
<?php class UUID { /** * Generates version 1: MAC address */ public static function v1() { if (!function_exists('uuid_create')) return false; uuid_create(&$context); uuid_make($context, UUID_MAKE_V1); uuid_export($context, UUID_FMT_STR, &$uuid); return trim($uuid); } /** * Generates version 3 UUID: MD5 hash of URL */ public static function v3($i_url) { if (!function_exists('uuid_create')) return false; if (!strlen($i_url)) $i_url = self::v1(); uuid_create(&$context); uuid_create(&$namespace); uuid_make($context, UUID_MAKE_V3, $namespace, $i_url); uuid_export($context, UUID_FMT_STR, &$uuid); return trim($uuid); } /** * Generates version 4 UUID: random */ public static function v4() { if (!function_exists('uuid_create')) return false; uuid_create(&$context); uuid_make($context, UUID_MAKE_V4); uuid_export($context, UUID_FMT_STR, &$uuid); return trim($uuid); } /** * Generates version 5 UUID: SHA-1 hash of URL */ public static function v5($i_url) { if (!function_exists('uuid_create')) return false; if (!strlen($i_url)) $i_url = self::v1(); uuid_create(&$context); uuid_create(&$namespace); uuid_make($context, UUID_MAKE_V5, $namespace, $i_url); uuid_export($context, UUID_FMT_STR, &$uuid); return trim($uuid); } } ?>
$mysqldate = date( 'Y-m-d H:i:s' );
/////////////////////////////////////////////////////////////////////////// // Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// function wasChown($path, $uid, $gid) { switch(filetype($path)) { case 'dir': if(($dir = opendir($path)) ==== false) break; while(false !== ($file = readdir($dir))) { if($file == '.' || $file == '..') continue; wasChown($path.'/'.$file, $uid, $gid); } case 'file': chown($path, $uid); chgrp($path, $gid); break; } }
Prepared statements are preferable where users can otherwise inject arbitrary code. In PHP
, PDO
is a good library that can be used to created prepared statements and thereby alleviate the need to sanitise user-input.
The following example for PHP
and MySQL
will insert a record into a table profile
with the structure such as:
Killer | ID |
---|---|
Chris Myass | 372453 |
The varaibles DATABASE
, HOST
, USERNAME
and PASSWORD
have to be defined and the variables killer
and id
have to be sent via POST:
$db = new PDO('mysql:dbname=DATABASE;host=HOST', USERNAME, PASSWORD); $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); try { $q = $db->prepare("INSERT INTO Profile(Killer, ID) VALUES(:killer, :id)"); $q->execute( array( ':killer' => $_POST['killer'], ':name' => $_POST['id'] ) ); } catch (PDOException $e) { die($e->getMessage); }
Upon a failure to insert the row, the catch
block triggers and the script dies while printing out the error message.
There are several variants to print unicode characters using PHP
, one of them is to use:
mb_convert_encoding('♥', 'UTF-8', 'HTML-ENTITIES');
where ♥
is the html entity corresponding to a ♥
character.
Another variant is to use:
html_entity_decode('♥', 0, 'UTF-8')
which will also print the ♥
character.
A very fast, yet ugly method of printing unicode characters is to use JSON:
$unicodeChar = '\u2665'; echo json_decode('"'.$unicodeChar.'"');
which is fast compared to the previous variants.
Transactions ensure ACID properties.
try { // Set the error mode to exceptions. $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // Begin the transaction $db->beginTransaction(); // A set of queries; if one fails, an exception should be thrown. // The transaction guarantees the atomicity of multiple queries. $db->query('first query'); $db->query('second query'); $db->query('third query'); // If we arrive here, it means that no exception was thrown // i.e. no query has failed, and we can commit the transaction $db->commit(); } catch (Exception $e) { // An exception has been thrown so we rollback the transaction. $db->rollback(); }
Using DOM we can traverse an entire XML structure and print out the nodes and their values in PHP.
# recurse over all nodes function traverse(DomNode $node, $level = 0) { # print the current node print_node($node, $level); # if there are sub-nodes if ($node->hasChildNodes()) { # for each sub-node foreach($node->childNodes as $child) { # if it is a node if ($child->nodeType == XML_ELEMENT_NODE) { # recurse all sub-nodes traverse($child, $level + 1); } } } } # determine if a node has children function hasChild($parent) { if ($parent->hasChildNodes()) { foreach($parent->childNodes as $child) { if ($child->nodeType == XML_ELEMENT_NODE) return true; } } return false; } # print the node with indenting function print_node(DomNode $node, $level) { # print indenting do { print "\t"; } while (--$level > -1); # print tag name if ($node->nodeType == XML_ELEMENT_NODE) { print $node->tagName; if (!hasChild($node)) { print " -> "; print $node->nodeValue; } } print "\n"; } # create a new DOM document $doc = new DomDocument("1.0"); # load an XML file $doc->loadXML(file_get_contents('Corrade.ini')); # the root is the first child $root = $doc->firstChild; # traverse the XML traverse($root);
Since file-operations are generally not atomic operations, we can encase read and write operations using flock
. Thus, we obtain the equivalent of file_put_contents
:
########################################################################### ## Copyright (C) Wizardry and Steamworks 2015 - License: GNU GPLv3 ## ########################################################################### function atomized_put_contents($file, $data) { $fp = fopen($file, "w+"); if (flock($fp, LOCK_EX)) { fwrite($fp, $data); fflush($fp); flock($fp, LOCK_UN); } fclose($fp); }
and the equivalent of file_get_contents
:
########################################################################### ## Copyright (C) Wizardry and Steamworks 2015 - License: GNU GPLv3 ## ########################################################################### function atomized_get_contents($file) { $fp = fopen($file, "r+"); $ct = ''; if (flock($fp, LOCK_SH)) { if (filesize($file)) { $ct = fread($fp, filesize($file)); } flock($fp, LOCK_UN); } fclose($fp); return $ct; }
Note that atomized_get_contents
is used like a generator function (requires PHP 5.5 where generators were introduced) and that whilst the functions are not atomic, the atomicity of the read and write operations is guaranteed provided the underlying system respects the file locks.
Given an array of elements these functions permute the array a certain number of times in both forward and reverse directions.
The wasReversePermuteArrayElements
function permutes the elements of an array in reverse.
Given an array containing the elements:
a b c
and calling the wasReversePermuteArrayElements
function with the times
parameter set to 1
, we obtain an array containing the elements:
b c a
########################################################################### ## Copyright (C) Wizardry and Steamworks 2015 - License: GNU GPLv3 ## ########################################################################### function wasReversePermuteArrayElements($input, $times) { if ($times == 0) return $input; return wasReversePermuteArrayElements( array_merge( array_slice( $input, 1 ), array_slice( $input, 0, 1 ) ), --$times ); }
The wasForwardPermuteArrayElements
function permutes the elements of an array forward.
Given a array string containing the elements:
a b c
and calling wasForwardPermuteArrayElements
function with the times
parameter set to 1
, we obtain the elements:
c a b
########################################################################### ## Copyright (C) Wizardry and Steamworks 2015 - License: GNU GPLv3 ## ########################################################################### function wasForwardPermuteArrayElements($input, $times) { if ($times == 0) return $input; return wasForwardPermuteArrayElements( array_merge( array_slice( $input, -1, 1 ), array_slice( $input, 0, -1 ) ), --$times ); }
The following is a list of cyphers implemented in PHP by Wizardry and Steamworks:
that can be used to encrypt and decrypt data.
The mapValueToRange
takes as input a value
with a range between xMin
and xMax
and scales the value
in a range given by yMin
and yMax
:
########################################################################## ## Copyright (C) Wizardry and Steamworks 2015 - License: GNU GPLv3 ## ########################################################################### function mapValueToRange($value, $xMin, $xMax, $yMin, $yMax) { return $yMin + ( ( $yMax - $yMin ) * ( $value - $xMin ) / ( $xMax - $xMin ) ); }
As an example, you can map an RGB component in the interval to a range by issuing:
echo mapValueToRange(128, 0, 255, 0, 1);
which will return approximately 0.50196078431373
.
One of the problems in programming is frequently the need to return a indexed sub-set of elements from a given set. For example, given the set :
we want to obtain the sub-set :
where:
This can be elegantly accomplished in PHP with the function wasArrayStride
:
########################################################################### ## Copyright (C) Wizardry and Steamworks 2015 - License: GNU GPLv3 ## ########################################################################### function wasArrayStride($a, $s) { return array_filter($a, function($e, $i) use($s) { return $i % $s == 0; }, ARRAY_FILTER_USE_BOTH ); }
As an example, running:
$a = array("a", "b", "c", "d", "e", "f"); var_dump(wasArrayStride($a, 2));
will return:
a c e
Note that if you wanted to obtain every third element, as in the sequence:
c f
then you would call something like:
var_dump( wasArrayStride( array_slice( $a, 2 ), 3 ) );
########################################################################### ## Copyright (C) Wizardry and Steamworks 2015 - License: GNU GPLv3 ## ########################################################################### function wasHexToRGB($hexStr, $toString = false, $seperator = ',') { $hexStr = preg_replace("/[^0-9A-Fa-f]/", '', $hexStr); $rgbArray = array(); switch(strlen($hexStr)) { case 6: $colorVal = hexdec($hexStr); $rgbArray['red'] = 0xFF & ($colorVal >> 0x10); $rgbArray['green'] = 0xFF & ($colorVal >> 0x8); $rgbArray['blue'] = 0xFF & $colorVal; break; case 3: $rgbArray['red'] = hexdec( str_repeat(substr($hexStr, 0, 1), 2)); $rgbArray['green'] = hexdec( str_repeat(substr($hexStr, 1, 1), 2)); $rgbArray['blue'] = hexdec( str_repeat(substr($hexStr, 2, 1), 2)); break; default: return false; } return $toString ? implode($seperator, $rgbArray) : $rgbArray; }
You can then make a call such as:
var_dump(hex2RGB(wasColorHash("Kira Komarov"), true));
Sometimes one needs to create a color to represent some data - for instance, to assign an unique color to a name. One very simple way to do that is to hash the string using some algorithm such as MD5 or SHA and then extract three pairs of two hexadecimal numbers from the hash. A good position is the start, the middle and the end which is what the wasColorHash
function does:
########################################################################### ## Copyright (C) Wizardry and Steamworks 2015 - License: GNU GPLv3 ## ########################################################################### function wasColorHash($a) { $hash = sha1($a); $size = strlen($hash); return substr($hash, 0, 2). substr($hash, $size/2, 2). substr($hash, $size-2, 2); }
This gives us a total of 16777215
possible variations and, given a good hash, that would mean a 0.000005960465%
probability to select an unique color from the range.
The wasResizePNG
function resizes a PNG image with libgd
given:
$img
,$w
,$h
.########################################################################### ## Copyright (C) Wizardry and Steamworks 2016 - License: GNU GPLv3 ## ########################################################################### function wasResizePNG($img, $w, $h) { $width = imagesx($img); $height = imagesy($img); $new = imagecreatetruecolor($w, $h); imagecolortransparent( $new, imagecolorallocate( $new, 0, 0, 0 ) ); imagecopyresampled( $new, $img, 0, 0, 0, 0, $w, $h, $width, $height ); imagedestroy($img); return $new; }
The wasAddBorderPNG
adds a border to an existing image with a given size and color. The wasAddBorderPNG
function takes as parameters:
$img
,$size
,red
, green
, blue
to values in the range .########################################################################### ## Copyright (C) Wizardry and Steamworks 2016 - License: GNU GPLv3 ## ########################################################################### function wasAddBorderPNG($img, $size, $color) { $width = imagesx($img); $height = imagesy($img); $img_adj_width = $width + (2 * $size); $img_adj_height = $height + (2 * $size); $new = imagecreatetruecolor( $img_adj_width, $img_adj_height ); imagecolortransparent( $new, imagecolorallocate( $new, 0, 0, 0 ) ); $color = imagecolorallocate( $new, $color['red'], $color['green'], $color['blue'] ); imagefilledrectangle( $new, 0, 0, $img_adj_width, $img_adj_height, $color ); imagecopyresized( $new, $img, $size, $size, 0, 0, $width, $height, $width, $height ); imagedestroy($img); return $new; }
An example call is the following:
$img = imagecreatefrompng('was.png'); # Add a red 5-pixel border around the image. $img = wasAddBorderPNG( $img, 5, array( "red" => 255, "green" => 0, "blue" => 0 ) );
A stack implementation in PHP can be found on the PHP stack data-structure page.
A queue implementation in PHP can be found on the PHP queue data-structure page.
By expressing the combinator using the combinator as explained, the combinator can be implemented in PHP.
<?php ########################################################################### ## Copyright (C) Wizardry and Steamworks 2016 - License: GNU GPLv3 ## ########################################################################### $w = function($f) { return $f($f); }; $Y = function($g) use ($w) { return $w( function($f) use ($g, $w) { return $g( function ($x) use ($f, $w) { $f = $w($f); return $f($x); } ); } ); };
An example call, to calculate the factorial of , would be:
$factorial = $Y( function($f) { return function($n) use($f) { return $n <= 1 ? 1 : $n * $f($n - 1); }; } ); echo $factorial(6);
You might get errors similar to:
php5-fpm[12598]: segfault at 7ffd38fdfff8 ip 00007fe1ec22ad8d sp 00007ffd38fdfe50 error 6 in libpcre.so.3.13.1[7fe1ec217000+6c000]
in which case, you should set a PCRE recursion limit. This can be achieved by editing your PHP configuration (php.ini
) and setting pcre.recursion_limit
to some value:
pcre.recursion_limit=100
This can be accomplished using var_export
instead of var_dump
:
echo '<pre>' . var_export($data, true) . '</pre>';
The following script will create a zip file from the directory specified in the configuration section by the variable ZIP_DIRECTORY
and will force the browser to download the file with the filename specified by ZIP_FILE_NAME
.
<?php ########################################################################### ## Copyright (C) Wizardry and Steamworks 2017 - License: GNU GPLv3 ## ########################################################################### ########################################################################### # CONFIGURATION # ########################################################################### # The directory to compress. $ZIP_DIRECTORY = getcwd().'/data/'; # The downloaded Zip file name. $ZIP_FILE_NAME = 'Corrade-'.basename(__DIR__).'.zip'; ########################################################################### # INTERNALS # ########################################################################### # Create temporary directory. function tempdir() { $tempfile = tempnam(sys_get_temp_dir(),''); # you might want to reconsider this line when using this snippet. # it "could" clash with an existing directory and this line will # try to delete the existing one. Handle with caution. if (file_exists($tempfile)) unlink($tempfile); mkdir($tempfile); if (is_dir($tempfile)) return $tempfile; } $tempDir = tempdir(); if(empty($tempDir)) exit('Could not create temporary directory'); $tempFile = $tempDir.'/'.$ZIP_FILE_NAME; # Initialize archive object $zip = new ZipArchive(); $zip->open($tempFile, ZipArchive::CREATE | ZipArchive::OVERWRITE | ZipArchive::CHECKCONS); # Create recursive directory iterator /** @var SplFileInfo[] $files */ $files = new RecursiveIteratorIterator( new RecursiveDirectoryIterator($ZIP_DIRECTORY), RecursiveIteratorIterator::LEAVES_ONLY ); foreach($files as $name => $file) { # Skip directories (they would be added automatically) if($file->isDir()) continue; # Get real and relative path for current file $filePath = $file->getRealPath(); $relativePath = substr($filePath, strlen($ZIP_DIRECTORY)); # Add current file to archive $zip->addFile($filePath, $relativePath); } # Zip archive will be created only after closing object $zip->close(); if(!file_exists($tempFile)) exit('Zip file was not created.'); # Set headers and send file. header('Pragma: public'); header('Expires: 0'); header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); header('Last-Modified: ' . gmdate('D, d M Y H:i:s', filemtime($tempFile)) . ' GMT'); header('Content-Type: application/force-download'); header('Content-Disposition: inline; filename="'.$ZIP_FILE_NAME.'"'); header('Content-Transfer-Encoding: binary'); header('Content-Length: ' . filesize($tempFile)); header('Connection: close'); readfile($tempFile); # Remove temporary directory and contents. $files = new RecursiveIteratorIterator( new RecursiveDirectoryIterator($tempDir, RecursiveDirectoryIterator::SKIP_DOTS), RecursiveIteratorIterator::CHILD_FIRST ); foreach($files as $name => $file) { if($file->isDir()) { rmdir($file->getRealPath()); continue; } unlink($file->getRealPath()); } rmdir($tempDir);
This script is used to create zip files from the various releases to be found in the Corrade Stitch repository.