Fizz Buzz and Fibbonacci combined

May 11th, 2017

I had a job interview recently and I was asked to do FizzBuzz.

The code is very simple to write, however I wanted to see if I could make it easily accept any series of numbers and easily alter its output.

The code I came up within an hour or so is below, but its use comes down to the simple one liners;

// Simple demo of numbers 0-5, default behaviour, no args
foreach(NumbersDirector::create() AS $number) echo "$number,";

Output: 0, 1, 2, 3, 4, 5

// Fizz Buzz from 1-100 using fizzbuzz factory builder
foreach(NumbersDirector::create(new NumericalSeries(array('start'=>1,'end'=>100)),new FizzBuzzBuilder()) AS $number) echo "$number,";

Output: 1,2,Fizz,4,Buzz,Fizz,7,8,Fizz,Buzz,11,Fizz,13,14,FizzBuzz,16,17,Fizz,19,Buzz,Fizz,22,23,Fizz,Buzz,26,Fizz,28,29,FizzBuzz,………………..

// Fibo from 0-2000
foreach(NumbersDirector::create(new FibbonacciSeries(array('end'=>2000))) AS $number) echo "$number,";

Output: 1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,1597,2584,

// Fibo from 2000-50000000 using fizzbuzz factory builder
foreach(NumbersDirector::create(new FibbonacciSeries(array('start'=>2000,'end'=>50000000)),new FizzBuzzBuilder()) AS $number) echo "$number,";

Output: Fizz,5998,9997,Buzz,Fizz,41987,67979,109966,FizzBuzz,287911,465856,753767,Fizz,Buzz,3193013,5166403,Fizz,13525819,Buzz,35411054,Fizz,

As you can see the last one is passing in a custom series and modifying the output to FizzBuzz.

It uses several patterns, ReadOnly, Factory, Director, Builder and returns an iterable instance, just a coding exercise really.

Full code below if anyone would care to see:

<?php
/*
Traits
*/
Trait Iterable{
 
	protected $_position;
    protected $_data;
 
    public function rewind() {
        $this->_position = 0;
    }
    public function current() {
        if ($this->valid()){
            $data = $this->getData();
            return $data[$this->_position];
        } 
 
    }
    public function key() {
        return $this->_position;
    }
    public function next() {
        ++$this->_position;
    }
    public function valid() {
        $data = $this->getData();
        return isset($data[$this->_position]);
    }
 
    protected function setData(array $data = null){
        $this->_data = $data;
        $this->rewind();
        return $this;
    }
 
    public function getData(){
 
        if (!isset($this->_data)){
            $this->setData();
        }
        return $this->_data;
    }
 
    public function getStart(){
 
        if (isset($this->_data[0])){
            return $this->_data[0];
        }
        return null;
    }
 
    public function getEnd(){
        $count = count($this->_data)-1;
        if ($count>0){
            return $this->_data[$count];
        }
 
        return null;
    }
 
    /*
     * Required by countable
     */
    public function count(){
        return count($this->_data);
    } 
}
 
trait Readonly{
 
 
    public function __construct(array $options = null)
    {     
        if (is_array($options)) {
            $this->setOptions($options);
        }
    }
 
    public function __set($name, $value)
    {
        $method = 'set' . $name;
        if (method_exists($this, $method)) {
            $this->$method($value);
            return $this;
        }
 
        throw new \Exception('"'.$name.'" is an invalid property of '.__CLASS__.' assignment of "'.$value.'" failed!');
 
    }
    public function __get($name)
    {
 
        $method = 'get' . $name;
        if (method_exists($this, $method)) {
            return $this->$method();
        }
 
        throw new \Exception('Invalid '.__CLASS__.' property '.$name);
    }
 
    public function setOptions(array $options)
    {
        $methods = get_class_methods($this);
        foreach ($options as $key => $value) {
            $method = 'set' . ucfirst($key);
            if (in_array($method, $methods)) {
                $this->$method($value);
            }
        }
        return $this;
    } 
} 
 
 
/*
Interfaces
*/
Interface SeriesInterface {
 
	public function generate();
}
 
Interface BuildersInterface {
 
	public function build($entry);
}
 
Interface ValueInterface {
    public function getValue();
    public function setValue();
    public function __toString();
}
 
/*
Abstract classes 
*/
abstract class Series implements SeriesInterface {
 
	use Readonly;
 
	protected $_start;
	protected $_end;
 
	public function setStart($start = 0){
		$this->_start = $start;
		return $this;
	}
 
	public function getStart(){
		if (!isset($this->_start)){
			$this->setStart();
		}
		return $this->_start;
	}
 
	public function setEnd($end = 5){
		$this->_end = $end;
		return $this;
	}
 
	public function getEnd(){
		if (!isset($this->_end)){
			$this->setEnd();
		}
		return $this->_end;
	}
 
	abstract function generate();
 
}
 
abstract class Value implements ValueInterface {
 
	use Readonly;
 
	protected $_val;
 
	public function getValue(){
        if (!isset($this->_val)){
            $this->setValue();
        }
        return $this->_val;
    }
    public function setValue($val = 0){
        if (!is_int($val)){
			throw new Exception('Expected integer as value got '.getType($val)); // would normally be the signature
		}
        $this->_val = $val;
        return $this;
    }
 
    abstract public function __toString();
 
}
 
/*
Classes
*/
class NumbersDirector implements Iterator{
 
	use Iterable;   
 
	protected function __construct(){}
	public function create(SeriesInterface $series = null, BuildersInterface $builder = null){
 
		if (is_null($series)){
			$series = new NumericalSeries();
		}
 
		if (is_null($builder)){
			$builder = new NumericalBuilder();
		}
 
		$stack = array();
 
		foreach($series->generate() AS $entry){
			$stack[]= $builder->build($entry);
		}
 
		$me = new self();
		$me->setData($stack); 
		return $me;
	}
 
}
 
class NumericalSeries extends Series {
 
	public function generate(){
 
		$series 	= array();
 
		for ($x=$this->start; $x<($this->end + 1); $x++){
			$series[] = $x;
		}
 
		return $series;
	}
}
 
class FibbonacciSeries extends Series {
 
 
    /**
     * Fibonacci using Binet's formula
     * @link http://mathworld.wolfram.com/BinetsFibonacciNumberFormula.html
     */
    public function binet($n)
    {
        $phi = (1 + sqrt(5)) / 2;
        return (pow($phi, $n) - pow(1 - $phi, $n)) / sqrt(5);
    }
 
    public function setStart($start = 1){
		$this->_start = $start;
		return $this;
	}
 
	public function setEnd($end = 55){
		$this->_end = $end;
		return $this;
	}
 
	public function generate(){
 
		$series 	= array();
		$fib 		= [$this->start,$this->start - 1];
		$next 		= 0;
		while($next < $this->end) {
		    $next = array_sum($fib);
		    array_shift($fib);
		    array_push($fib,$next);
		    $series[]=$next;
		}
		return $series;
	}
}
 
class NumericalBuilder implements BuildersInterface {
 
	public function Build($entry){
 
		$number 		=  new Number();
		$number->value 	= $entry;
		return $number;
	}
 
}
 
class FizzBuzzBuilder implements BuildersInterface {
 
	public function Build($entry){
 
		/* 
		Factory method
		*/
		$class 	= "";
 
		if ($entry%3==0){
			$class.= 'Fizz';
		}
 
		if ($entry%5==0){
			$class.= 'Buzz';
		}
 
		if (!class_exists($class) || !isset(class_implements($class)['ValueInterface'])){
			$class = "Number";
		}
 
		$number 		=  new $class();
		$number->value 	= $entry;
		return $number;
 
	}
 
}
 
class Number extends Value {
    public function __toString(){
		return (string) $this->getValue();
	}	
}
 
class Buzz extends Value {
	public function __toString(){
		return (string) 'Buzz';
	}
}
 
class Fizz extends Value {
	public function __toString(){
		return (string) 'Fizz';
	}
}
 
class FizzBuzz extends Value {
	public function __toString(){
		return (string) 'FizzBuzz';
	}
}
 
 
 
// Simple demo of numbers 0-5, default behaviour, no args
foreach(NumbersDirector::create() AS $number) echo "$number,";
echo "<hr />";
// Fizz Buzz from 1-100 using fizzbuzz factory builder
foreach(NumbersDirector::create(new NumericalSeries(array('start'=>1,'end'=>100)),new FizzBuzzBuilder()) AS $number) echo "$number,";
echo "<hr />";
// Fibo from 0-2000
foreach(NumbersDirector::create(new FibbonacciSeries(array('end'=>2000))) AS $number) echo "$number,";
echo "<hr />";
// Fibo from 2000-50000000 using fizzbuzz factory builder
foreach(NumbersDirector::create(new FibbonacciSeries(array('start'=>2000,'end'=>50000000)),new FizzBuzzBuilder()) AS $number) echo "$number,";
VN:F [1.9.9_1125]
Rating: 0.0/10 (0 votes cast)
VN:D [1.9.9_1125]
Rating: +1 (from 1 vote)
496 views

running PHP 7 and PHP 5 together – ubuntu

March 22nd, 2017

Install the dependancies

sudo add-apt-repository ppa:ondrej/php
sudo apt-get update
sudo apt-get install php7.0 php5.6 php5.6-mysql php-gettext php5.6-mbstring php-mbstring php7.0-mbstring php-xdebug libapache2-mod-php5.6 libapache2-mod-php7.0

Switch from 7 to 5

sudo a2dismod php7.0
sudo a2enmod php5.6
sudo service apache2 restart

Switch from 5 to 7

sudo 2dismod php5.6 
sudo a2enmod php7.0  
sudo service apache2 restart
VN:F [1.9.9_1125]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.9_1125]
Rating: 0 (from 0 votes)
716 views

WordPress, concrete5, ZF2, PHP, mysql database dump

March 22nd, 2017

Here is a very simple script that once uploaded locks onto various architectures and extracts the database using the captured details.

For example, wordpress and concrete5 have been detected here:

Screenshot from 2017-03-22 11-18-40

When nothing is detected it will still offer the manual entering of the username and password.

Screenshot from 2017-03-22 11-18-47

It currently supports Concrete5 and WordPress, but I can easily upgrade it to support many more like ZF1, ZF2, Magento, Drupal, Joomla, etc, if there is any interest.

This is handy when you need to quickly copy a database, you simply upload this script to the doc_root and the script will attempt to handle the rest for you.

The script comes with password protection to prevent unauthorised usage, or it will not just be you downloading the database.

Screenshot from 2017-03-22 12-28-36

The script stores the username and password of those authorised to use it within the code, the password can be entered in plain text, or you can define your own algorithm and store the password encrypted in this way, within the code.

The script can be downloaded from github here and the full source code is below.

/*
 
 
Adrian Callaghan 21 Mar 2017 
 
Very lightweight database dumper that automatically locks access details provided by other PHP frameworks
 
 
 
****** How to use ******
 
Enter your usernames and passwords into the constructor in either plain text (insecure if read by someone else) or encypted
 
 
 
Example 1: allowing bob access with the password 1234 and joe access with password 5678 - no encryption 
 
	dbDump::Init(array(
		'users'	=> array(
			array('username'=>'bob','password'=>'1234'),
			array('username'=>'joe','password'=>'5678'),
		)));
 
 
 
Example 2: allowing bob access with the password 1234 and joe access with password 5678 - with encyption method and hashed passwords that must match the method result
 
	dbDump::Init(array(
		'users'	=> array(
			array('username'=>'bob','password'=>'81dc9bdb52d04dc20036dbd8313ed055'),
			array('username'=>'joe','password'=>'674f3c2c1a8a6f90461e8a66fb5550ba'),
		),
		'passwordEncryption'=>function($pass){
			return md5($pass);
		}
	));
 
*/
 
 
 
 
/******************
 
Constructor
 
*******************/
dbDump::Init(array(
	'users'	=> array(
		array('username'=>'bob','password'=>'81dc9bdb52d04dc20036dbd8313ed055'),
		array('username'=>'joe','password'=>'674f3c2c1a8a6f90461e8a66fb5550ba'),
	),
	'passwordEncryption'=>function($pass){
		return md5($pass);
	}
));
 
 
 
 
 
 
 
/******************
 
Class starts...
 
*******************/
final class dbDump{
 
	const APP_STATE = 'state';
	const APP_AUTH 	= 'MY_TOKEN';
	const APP_SALT  = 'MY_SALT';
 
	private $_users;
	private $_passwordEncryption;
 
	protected function destroySession(){
		$this->initSession();
		session_destroy();
		return $this;
	}
 
	protected function initSession(){
		if (session_status() == PHP_SESSION_NONE) {
		    session_start();
		}
 
		return $this;
	}
 
	protected function getSession($object = true){
		$this->initSession();
		return $object ? (object) $_SESSION : $_SESSION;
    }
 
   	protected function getSessionVar($var = ''){
   		return isset($this->session->{$var}) ? $this->session->{$var} : false;
    }
 
    protected function setSessionVar($key, $val){
    	$session 			= $this->session;
    	$session->{$key} 	= $val;
    	$this->session = (array) $session;
    }
 
    protected function setSession(array $values){
    	$this->initSession();
    	$_SESSION = $values;
    	return $this;
    }
 
	protected function getGet($object = true){
		return $object ? (object) $_GET : $_GET;
	}
 
	protected function getGetVar($var = ''){
   		return isset($this->post->{$var}) ? $this->post->{$var} : false;
    }
 
    protected function isPost(){
    	return empty($this->getPost(false)) ? false : true;
    }
 
	protected function getPost($object = true){
		return $object ? (object) $_POST : $_POST;
	}
 
	protected function getPostVar($var = ''){
   		return isset($this->post->{$var}) ? $this->post->{$var} : false;
    }
 
	protected function getState(){
		return $this->getSessionVar(self::APP_STATE);
	}
 
	protected function setState($state = ''){
		$this->setSessionVar(self::APP_STATE, $state);
		return $this;
	}
 
	protected function is_constant($token) {
	    return $token == T_CONSTANT_ENCAPSED_STRING || $token == T_STRING || $token == T_LNUMBER || $token == T_DNUMBER;
	}
 
	protected function strip($value) {
	    return preg_replace('!^([\'"])(.*)\1$!', '$2', $value);
	}
 
	protected function getDefinitions($php){
 
		$defines 	= array();
		$state 		= 0;
		$key 		= '';
		$value 		= '';
		$tokens 	= token_get_all($php);
		$token 		= reset($tokens);
		while ($token) {
		//    dump($state, $token);
		    if (is_array($token)) {
		        if ($token[0] == T_WHITESPACE || $token[0] == T_COMMENT || $token[0] == T_DOC_COMMENT) {
		            // do nothing
		        } else if ($token[0] == T_STRING && strtolower($token[1]) == 'define') {
		            $state = 1;
		        } else if ($state == 2 && $this->is_constant($token[0])) {
		            $key = $token[1];
		            $state = 3;
		        } else if ($state == 4 && $this->is_constant($token[0])) {
		            $value = $token[1];
		            $state = 5;
		        }
		    } else {
		        $symbol = trim($token);
		        if ($symbol == '(' && $state == 1) {
		            $state = 2;
		        } else if ($symbol == ',' && $state == 3) {
		            $state = 4;
		        } else if ($symbol == ')' && $state == 5) {
		            $defines[$this->strip($key)] = $this->strip($value);
		            $state = 0;
		        }
		    }
		    $token = next($tokens);
		}
 
		return $defines;
 
	}
 
	protected function generateDbForm($fields = null, $forceDisplay = false){
 
		if ($fields===null && !$forceDisplay){
			return;
		}
 
		$form = "<form method='post' name='dbForm' class='form-horizontal col-vert-20' role='form'>";
 
		$form.= "<div class='form-group'><label class='col-sm-2&#x20;control-label'>Host</label><div class='col-sm-10'><input name='host' type='text' placeholder='Enter host name' required='required' class='form-control' value='".(isset($fields->host) ? $fields->host : '')."'></div></div>";
 
		$form.= "<div class='form-group'><label class='col-sm-2&#x20;control-label'>Table</label><div class='col-sm-10'><input name='table' type='text' placeholder='Enter table name' required='required' class='form-control' value='".(isset($fields->table) ? $fields->table : '')."'></div></div>";
 
		$form.= "<div class='form-group'><label class='col-sm-2&#x20;control-label'>User</label><div class='col-sm-10'><input name='username' type='text' placeholder='Enter user name' required='required' class='form-control' value='".(isset($fields->username) ? $fields->username : '')."'></div></div>";
 
		$form.= "<div class='form-group'><label class='col-sm-2&#x20;control-label'>Password</label><div class='col-sm-10'><input name='password' type='text' placeholder='Enter password' required='required' class='form-control' value='".(isset($fields->password) ? $fields->password : '')."'></div></div>";
 
		$form.= "<div class='form-group'><div class='col-sm-12'><button type='submit' name='button-submit' class='btn&#x20;btn-success btn-lg pull-right' value=''>
		<span class='glyphicon glyphicon-download'></span>&nbsp;Download</button></div></div>";
 
 
		$form.= "</form>";
 
 
		return $form;
	}
 
	protected function getPlatform($options){
 
		$error          = '<div class="pull-right text-warning"><span class="glyphicon glyphicon-warning-sign status"></span></div>';
		$notFound       = '<div class="pull-right text-danger"><span class="glyphicon glyphicon-remove status"></span></div>';
		$found          = '<div class="pull-right text-success"><span class="glyphicon glyphicon-ok status"></span></div>';
		$out			= '<li class="list-group-item">';
		$logoW			= isset($options->logoW) ? $options->logoW : '213';
		$logoH          = isset($options->logoH) ? $options->logoH : '120';
		$logo 			= "<img src='".(isset($options->logo) ? $options->logo : "holder.js/{$logoW}x{$logoH}")."' height='{$logoH}' width='{$logoW}' alt='platform logo' longdesc='logo representing the platform option' />";
		$dbArgs 		= new StdClass(); 
 
		if (isset($options->conf) && file_exists($options->conf)){
			if (($fp 	= fopen($options->conf, "r"))!==false){
				$params = (object) $this->getDefinitions(stream_get_contents($fp)); 
				foreach(array('host','table','username','password') AS $option){
						$dbArgs->{$option} = isset($options->{$option}) && isset($params->{$options->{$option}}) ? $params->{$options->{$option}} : '';
				}				
	      		$out	.= $found.$logo.$this->generateDbForm($dbArgs, isset($options->force) ? $options->force : null);
	      		fclose($fp);
	      	} else {
	      		$out	.= $error.$logo.$this->generateDbForm(null, isset($options->force) ? $options->force : null);
	      	}
		} else {
			$out		.= $notFound.$logo.$this->generateDbForm(null, isset($options->force) ? $options->force : null);
		}
		$out.= '</li>';
 
		return $out;
 
	}
 
	protected function getPlatforms(){
 
		$out 			= '<ul class="list-group">';
		$out			.= $this->getPlatform((object) array(
			'conf'		=> 'wp-config.php',
			'logo'		=> 'https://s.w.org/about/images/logos/wordpress-logo-32-blue.png',
			'logoW'		=> '32',
			'logoH'		=> '32',
			'host'		=> 'DB_HOST',
	      	'table'		=> 'DB_NAME',
	      	'username'	=> 'DB_USER',
	      	'password' 	=> 'DB_PASSWORD'
			));
 
		$out			.= $this->getPlatform((object) array(
			'conf'		=> 'config/site.php',
			'logo'		=> 'https://www.concrete5.org/files/3613/5517/8150/concrete5_Wordmark_200x37.png',
			'logoW'		=> '200',
			'logoH'		=> '37',
			'host'		=> 'DB_SERVER',
	      	'table'		=> 'DB_DATABASE',
	      	'username'	=> 'DB_USERNAME',
	      	'password' 	=> 'DB_PASSWORD'
			));
 
		/*$out			.= $this->getPlatform((object) array(
			'conf'		=> 'config/autoload/local.php',
			'logo'		=> 'http://clloh.com/wp-content/uploads/2015/08/zf2-logo-128x128.png',
			'logoW'		=> '128',
			'logoH'		=> '128',
			'host'		=> 'DB_SERVER',
	      	'table'		=> 'DB_DATABASE',
	      	'username'	=> 'DB_USERNAME',
	      	'password' 	=> 'DB_PASSWORD'
			));*/
 
		$out			.= $this->getPlatform((object) array(
			'logo'		=> 'https://www.mysql.com/common/logos/logo-mysql-170x115.png',
			'logoW'		=> '170',
			'logoH'		=> '115',
			'force'		=> true,
			));
 
 
		return $out.'</ul>';
	}
 
	protected function getHeader(){
		return '<html><head><title>Restricted area</title><link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"><script src="https://code.jquery.com/jquery-3.2.1.js" integrity="sha256-DZAnKJ/6XZ9si04Hgrsxu/8s717jcIzLy3oi35EouyE=" crossorigin="anonymous"></script><script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/holder/2.9.4/holder.js"></script><META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW"><style>.col-vert-20{margin-top:20px;}.col-vert-100{margin-top:100px;}.status{font-size:30px;}</style></head><body><div class="container-fluid"><div class="row">';
	}
 
	protected function getFooter(){
		$footer = '</div></div>';
 
		if ($this->authentication) {
 
			$footer .= '<div class="modal fade" id="confirmationModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
				  <div class="modal-dialog modal-sm" role="document">
				    <div class="modal-content">
				      <div class="modal-header">
				        <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
				        <h4 class="modal-title" id="myModalLabel"><span class="glyphicon glyphicon-lock"></span>&nbsp;Log out request.</h4>
				      </div>
				      <div class="modal-body">
				        Are you sure you wish to logout '.$this->authentication->username.'?
				      </div>
				      <div class="modal-footer">
				        <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
				        <a type="button" class="btn btn-primary" href="?logout=true">Confirm</a>
				      </div>
				    </div>
				  </div>
				</div>
				</body></html>';
		}
 
		return $footer;
	}
 
	protected function loginForm($inErrorState = false){
		return '<div class="col-md-6 well well-large col-md-offset-3 col-vert-100"><h3><span class="glyphicon glyphicon-lock"></span> '.($inErrorState ? 'Access Denied' : 'Secure Area' ).'</h3><form method="post" name="login" class="form-horizontal col-vert-20" role="form"><div class="form-group '.($inErrorState ? 'has-error' : '').'"><label class="col-sm-2&#x20;control-label">Username</label><div class=" col-sm-10"><input name="username" type="text" placeholder="Enter&#x20;username" required="required" class="form-control" value="">'.($inErrorState ? '<ul class="help-block"><li>Invalid username &amp; password combination</li></ul>' : '').'</div></div><div class="form-group '.($inErrorState ? 'has-error' : '').'"><label class="col-sm-2&#x20;control-label">Password</label><div class=" col-sm-10"><input name="password" type="password" required="required" placeholder="Password" class="form-control" value="">'.($inErrorState ? '<ul class="help-block"><li>Invalid username &amp; password combination</li></ul>' : '').'</div></div><div class="form-group "><div class=" col-sm-10 col-sm-offset-2"><button type="submit" name="button-submit" class="btn&#x20;btn-default" value="">Login</button></div></div></form></div>';
	}
 
	protected function getDownloadOptions($inErrorState = false){ 
		return '<div class="col-md-6 col-md-offset-3 col-vert-100"><div class="panel panel-primary"><div class="panel-heading"><span class="glyphicon glyphicon-wrench"></span>&nbsp;Export options<button class="pull-right btn btn-danger btn-xs" data-toggle="modal" data-target="#confirmationModal">'.$this->authentication->username.'&nbsp;<span class="glyphicon glyphicon-remove-circle"></span></button></div>'.$this->platforms.'</div></div>'; 
	}
 
	protected function setUsers(array $users = null){
        if ($users==null){
            $users = array();
        }
        foreach($users AS $key=>$user){
        	$users[$key] = (object) $user;
        }
        $this->_users = (object) $users;
        return $this;
    }
 
    protected function getUsers(){
 
        if (!isset($this->_users)){
            $this->setUsers();
        }
        return $this->_users;
    }
 
	protected function setPasswordEncryption($function = null){
        if ($function==null){
            $function = function($val){return $val;};
        }
        $this->_passwordEncryption = $function;
        return $this;
    }
 
    protected function getPasswordEncryption(){
 
        if (!isset($this->_passwordEncryption)){
            $this->setPasswordEncryption();
        }
        return $this->_passwordEncryption;
    }
 
    protected function PasswordEncrypt($pass = ''){
 
    	$encryptor 	= $this->getPasswordEncryption();
    	return call_user_func($encryptor, $pass);
 
    }
 
    protected function generateUserToken(\StdClass $user){
    	return md5((isset($user->username) ? $user->username : uniqid()).self::APP_SALT.(isset($user->password) ? $user->password : uniqid()));
    }
 
    protected function setAuthentication(\StdClass $user){
    	$this->setSessionVar(self::APP_AUTH, $this->generateUserToken($user));
    	return $this;
    }
 
    protected function getAuthentication(){
    	$token 	= $this->getSessionVar(self::APP_AUTH);
    	foreach($this->users AS $validUser){
    		$validToken = $this->generateUserToken($validUser);
    		if ($token==$validToken){
    			return $validUser;
    		}
    	}
 
    }
 
    protected function authenticateUser(\StdClass $user){
 
		foreach($this->users AS $validUser){
 
			if ($user->username==$validUser->username && $this->passwordEncrypt($user->password)==$validUser->password){
				$this->authentication 	= $validUser;
				$this->state 			= 'options';
				return $this->authentication;
			}
		}
 
    }
 
	public static function Init(array $options = array()){
 
		static $inst 	= null;
        if ($inst 		=== null) {
            $inst 		= new dbDump($options);
        }
 
        if (isset($inst->get->logout)){
        	$inst->destroySession();
        	header('Location: '.$_SERVER['PHP_SELF']);
        	die;
        }
 
        if (!$inst->authentication){
        	$inst->state = null;
        }
 
		switch($inst->state){
			case 'options':
 
				//var_dump($inst->authentication);
				if ($inst->isPost()){
 
					$hostname 	= $inst->getPostVar('host');
					$table 		= $inst->getPostVar('table');
					$username 	= $inst->getPostVar('username');
					$password 	= $inst->getPostVar('password');
					$command 	= "mysqldump --add-drop-table --host=$hostname --user=$username --password=$password $table";
 
					header('Content-Description: File Transfer');
					header('Content-Type: application/octet-stream');
					header('Content-Disposition: attachment; filename='.basename($table."_".date("Y-m-d_H-i-s").".sql"));
					system($command);
					exit();
				} else {
					echo $inst->header;					
					echo $inst->downloadOptions;
					echo $inst->footer;
				}
			break;
			default:
 
				if ($inst->isPost()){
					if ($inst->authenticateUser($inst->post)){
						$inst->state = 'options';
						header("Refresh:0");
						die;
					} else {
						echo $inst->header;
						echo $inst->loginForm(true);
						echo $inst->footer;
					}
 
				} else {
					echo $inst->header;
					echo $inst->loginForm();
					echo $inst->footer;
				}
			break;
		}
 
	}
 
    public function __set($name, $value)
    {
        $method = 'set' . $name;
        if (method_exists($this, $method)) {
            $this->$method($value);
            return $this;
        }
 
        throw new \Exception('"'.$name.'" is an invalid property of '.__CLASS__.' assignment failed!');
 
    }
 
    public function __get($name)
    {
 
        $method = 'get' . $name;
        if (method_exists($this, $method)) {
            return $this->$method();
        }
 
        throw new \Exception('Invalid '.__CLASS__.' property '.$name);
    }
 
    public function setOptions(array $options)
    {
        $methods = get_class_methods($this);
        foreach ($options as $key => $value) {
            $method = 'set' . ucfirst($key);
            if (in_array($method, $methods)) {
                $this->$method($value);
            }
        }
        return $this;
    }  
 
    private function __construct(array $options = null)
    {     
    	// env
    	set_time_limit(20);
 
        if (is_array($options)) {
            $this->setOptions($options);
        }
 
    }
 
	private function __clone(){}
}
VN:F [1.9.9_1125]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.9_1125]
Rating: 0 (from 0 votes)
828 views

How to create a ZF2 nested bootstrap dropdown menu

December 15th, 2016

To create a nested menu in ZF2 you will need to tell the ZF2 navigation service to use a partial containing code that creates new markup.

Here is a step by step example of how to output a nested menu in bootstraps markup in ZF2.

First you need to tell the navigation service to use a partial to render the menu, find where the navigation is called, typically this is the layout file found in

/module/Application/view/layout/layout.phtml

And looks something like:

echo $this->navigation('navigation')->menu();

To tell ZF2 navigation to use the partial myfile.phtml you simple append to the request setPartial and pass an array of arguments, the first argument contains the name of the partial file and the second the name of the module for example the first argument is ‘myfile.phtml’ and the second ‘default’ which is module Application.

echo $this->navigation('navigation')->menu()->setPartial(array('myfile.phtml','default'));

Note you would normally organise partials into their own folder to do this just prepend the folder name to the partial name for example ‘->setPartial(array(‘partial/myfile.phtml’,’default’)’

The ul class needs to be declared as ‘nav nav-bar’ which is used by bootstrap. Simply append this to the end as ->setUlClass(‘nav navbar-nav’) so your complete code should now look like

echo $this->navigation('navigation')->menu()->setPartial(array('myfile.phtml','default'))->setUlClass('nav navbar-nav');

Now create the partial file for the navigation service to use:

/module/Application/view/myfile.phtml

The partial will be used to render the navigation and this is where new logic to display the mark up should be contained.

The following example code will create a nested menu, with the correct mark up and classes that bootstrap recognises, add this to the partial created above.

<ul class="<?php echo $this->navigation()->menu()->getUlClass(); ?>">
 
    <?php call_user_func($selfRef = function($pages, $navigation, $level = 0, $id='lvl-%d-pos-%d') use (&$selfRef) {
 
        foreach ($pages as $pos=>$page){
 
            $page->setClass('nav-header');
            $liClasses          = array();
            $page->id           = sprintf($id, $level, $pos);
 
            /* manually check for ACL conditions */
            if(!$page->isVisible() || !$navigation->accept($page)) {
                continue;
            } 
 
            switch($level){
                case '0': 
                    if ($page->isActive()){
                        $liClasses[]    = 'active';
                    }
                    if($page->hasPages()){ 
                        $liClasses[]    = 'dropdown';
                        $page->setClass('dropdown-toggle');
                        $page->setLabel($page->getLabel().'&nbsp;<span class="caret"></span>');
                    } 
                break;
                default:
                    if($page->hasPages()){ 
                        $liClasses[]    = 'dropdown-submenu';
                    }
                break;
            }
 
            ?>
            <li id="<?php echo $page->id; ?>" <?php echo !empty($liClasses) ? 'class="'.implode(' ',$liClasses).'"' : ''; ?>>
                <a class="<?php echo $page->getClass(); ?>" href="<?php echo $page->getHref(); ?>" <?php if ($page->hasPages()) echo 'data-toggle="dropdown"'; ?>>
                    <?php echo $page->getLabel(); ?>
                </a>
                <?php if ($page->hasPages()) : ?>
                    <ul class="dropdown-menu" role="menu">
                        <?php $selfRef($page->getPages(), $navigation, $level+1, $id); // recursion ?>
                    </ul>
                <?php endif; ?>
            </li>
 
            <?php
        }
 
    }, 
    $this->container, 
    $this->navigation()
    );
 
?>
</ul>

The above code contains a simple function that loops through the pages checking if the current iteration has children or not.

If the iteration does not, a page link is rendered with the correct classes for that level. If the iteration does contain children additional markup is created the function then makes a recursive call to itself to render those pages when the call returns it generates closing markup.

When generating the markup the loop is aware of how deep within the menu structure it currently is. By being aware of the levels and positions CSS classes have been able to be applied at specific levels in addition to this extra markup such as carets has been injected into the top layer, indicating the presence of a drop down menu where present.

Happy coding!

VN:F [1.9.9_1125]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.9_1125]
Rating: +1 (from 1 vote)
1,138 views

Zend framework 2 DomPdf No block-level parent found. Not good. error message

July 25th, 2016

This error can be caused by many things, but the most notable is when attempting to reuse DomPdf to render more than one PDF.

This is to do with the way the service manager passes a single instance, and DOMPDF does not clean up after itself properly.

Attempting code like:

$html   = $this->getServiceLocator()->get('viewpdfrenderer')->getHtmlRenderer()->render($pdf);
$eng    = $this->getServiceLocator()->get('viewpdfrenderer')->getEngine();
 
$eng->load_html($html);
$eng->render();

Will fail, however despite the answer being very hard to find online the solution is rather simple, simply use the html renderer but request dompdf from the service manager, below I will render multiple PDF’s with different views, save them as files ready to be attached to an email.

 
        // first PDF
        $pdf = new PdfModel();
        $pdf->setTerminal(true);
        $pdf->setTemplate('template1');
        $pdf->setVariables(array(
          'foo'         => 'bar'
        ));
 
        $html                   = $this->getServiceLocator()->get('viewpdfrenderer')->getHtmlRenderer()->render($pdf);
        $dompdf                 = $this->getServiceLocator()->get('dompdf'); // get fresh instance everytime
 
        $dompdf->load_html($html);
        $dompdf->render();
        file_put_contents('file1.pdf', $dompdf->output());
 
 
 
 
        // second pdf
        $pdf = new PdfModel();
        $pdf->setTerminal(true);
        $pdf->setTemplate('template2');
        $pdf->setVariables(array(
          'foo'         => 'bar'
        ));
 
        $html                   = $this->getServiceLocator()->get('viewpdfrenderer')->getHtmlRenderer()->render($pdf);
        $dompdf                 = $this->getServiceLocator()->get('dompdf'); // get fresh instance everytime
 
        $dompdf->load_html($html);
        $dompdf->render();
        file_put_contents('file2.pdf', $dompdf->output());

Happy coding!

VN:F [1.9.9_1125]
Rating: 10.0/10 (2 votes cast)
VN:F [1.9.9_1125]
Rating: 0 (from 0 votes)
2,952 views

passing variables to get_template part in wordpress

July 23rd, 2015

When including part of a theme using the wordpress function get_template_part(), you will notice the included template will not have access to any variables previously defined, this is because they are now out of scope.

For example the template foo.php will not have access to $a:

$a =1;
get_template_part('foo');

There are two main work a rounds:

1. Global Technique

$a=1;
get_template_part('foo');

in foo.php

global $a;

By adding Global $a; into the template foo.php will allow the template to access the variable $a

2. Locate and include

$a=1;
include(locate_template('foo.php'));

By using locate_template to generate a path and php’s include it is possible to include the template as though it was a block of code in line with the existing code thus consequently has access to the current scope.

Both of which I am not keen on, the global fix (1) downside is that you will need to declare global on each and every variable you wish to use, and the use of global is bad.
The second, Locate and include (2) downside is that should the template not exist a warning will be displayed, this is because a check before hand is not being performed, this leads to more code to check for the files existence or suppress the error, furthermore the code included has the potential to modify any variables in the existing scope.

My approach is to use an extra function added to the themes functions.php file

$a=1;
get_partial('foo',array('a'=>$a)); 

The function behaves in the same way as get_template_part() but performs all the correct checks before hand thus stopping any errors, then assigns the variables to the scope, includes the template, and finally returns a success of true or false.

The function to add is below (simply copy and paste into functions.php)

function get_partial($template, array $args = array()){
    $template   = locate_template(preg_replace("/(.+)\.php$/", "$1", $template).'.php'); 
    if (file_exists($template)){
        global $posts, $post, $wp_did_header, $wp_query, $wp_rewrite, $wpdb, $wp_version, $wp, $id, $comment, $user_ID;
        extract($args);
        include($template);
        return true;
    }
}

Happy coding!

VN:F [1.9.9_1125]
Rating: 10.0/10 (1 vote cast)
VN:F [1.9.9_1125]
Rating: +1 (from 1 vote)
2,301 views

Script to monitor internet connection

April 21st, 2015

The internet often drops at work, so to compile a csv report of the outage time and for how long I wrote this script, which maybe of use to someone.

Simply create the script, with execution rights (sudo chmod a+x) and call the script with the first argument as a resource e.g google and the second argument as the output filename e.g ./monitor.sh google.co.uk myFile

Code below:

#!/bin/bash

resource=$1
outfile=$2
dwnTmp=".dwnLock";
upTmp=".upLock";

# NEED A RESOURCE
if [[ -z "$resource" ]]; then
      	echo "You must define a resource as the first parameter e.g google.co.uk";
	exit; 
fi
####

# NEED A FILENAME
if [[ -z "$outfile" ]]; then
      	echo "You must define an output file as the second parameter";
	exit; 
fi
####

### REMOVE LOCKS
if [ -f "$dwnTmp" ]; then
        rm $dwnTmp;
fi
if [ -f "$upTmp" ]; then
        rm $upTmp;
fi
#################

echo "Logging connectivity of http://$resource/ to $outfile.csv CTRL+C to exit"

# LOOP
count=0
while [ 1=1 ]; do

        let count+=1
        
        time=$(date +"%T")
        timeSec=$(date +%s)
        duration=0
        
        # log
        wget -q --tries=1 --timeout=10 --spider "http://$resource/"
        if [[ $? -eq 0 ]]; then
                if [ ! -f "$upTmp" ]; then
                
                        echo $timeSec > $upTmp;
                        
                        if [ -f "$dwnTmp" ]; then
                                duration=$(($timeSec-`cat $dwnTmp`))
                                rm $dwnTmp;
                                
                        fi
                        
                        echo -ne CHECK $count: AVAIL     '\r'
                        echo "$count,$time,Up after being down for $(($duration / 60)) minutes and $(($duration % 60)) seconds" >> "$outfile.csv"

                fi
        else
                if [ ! -f "$dwnTmp" ]; then
                
                        echo $timeSec > $dwnTmp;
                        
                        if [ -f "$upTmp" ]; then
                                duration=$(($timeSec-`cat $upTmp`))
                                rm $upTmp;
                        fi
                        echo -ne CHECK $count: ERROR   '\r'
                        echo "$count,$time,Down after being up for $(($duration / 60)) minutes and $(($duration % 60)) seconds" >> "$outfile.csv"
                fi
        fi
done
#####

VN:F [1.9.9_1125]
Rating: 10.0/10 (1 vote cast)
VN:F [1.9.9_1125]
Rating: +1 (from 1 vote)
2,309 views

Format a WD drive to linux

February 18th, 2015

After buying a WD drive, I found it was difficult to make it work with Linux.

After much googling it appeared a common problem, I found although Gparted claimed it had formatted the drive, it would not mount nor read and write.

It turns out WD has decided to include hidden partitions that make reformatting it almost impossible, WD calls this technology “Smart Ware”

However, I found a combination of G-Parted and Parted solved this (do not type the quotes):

1. Open G-Parted
2. Locate your device in the Gparted drop down menu (Make sure you select the right device)
3. Unmount any mounted partitions
4. Foreach partition select delete
5. Click new, Create one large partition and click Apply
6. Take note of the device name (for example “/dev/sdg”)
7. In terminal start parted with elevated privileges i.e sudo parted
8. At the prompt, select your drive with “select /dev/sdf”
9. Type “align-check” to check the alignment
10. At the prompt “alignment type(min/opt) [optimal]/minimal?” type “optimal”
11. Enter the partition number (Typically 1 for a single partition)
12. Type “quit”

You will likely see the drive in Nautilus but be unable to write to it, to fix this:

1. Open the drive in nautilus, right click properties and look for Location i.e “/run/media/adrian”
2. In Terminal, navigate to this folder i.e “cd /run/media/adrian”
3. “ls -la” will list your -device- and likely state it is drwxr-xr-x for root:root (not writable for you)
4. Type “sudo chmod 777 -R /run/media/adrian/-device-” (777 is rwx for everyone, I would recommend tailoring this to your requirements and is an example only)

VN:F [1.9.9_1125]
Rating: 9.0/10 (1 vote cast)
VN:F [1.9.9_1125]
Rating: +1 (from 1 vote)
2,364 views

Desktop tidy

December 3rd, 2014

A cluttered desktop can be a problem, typically people use the desktop becuase they know the location of the files should they have downloaded them from somewhere, and need to reuse them quickly.

I have written a script that runs on Linux that cleans the desktop up on a daily basis, by moving all the files into a folder with an easily readable date name within an archive folder, so that your desktop remains clean and ordered, and you also do not lose your files.

The beauty of this is that you can configure your applications to point at the desktop, safe in the knowledge that all the clutter from today will be gone tomorrow, and placed neatly within a folder with the date so you can find it, when somebody says “I sent it to you Tuesday”

Just run the script below and it will automatically install, any clutter on the Desktop will archive to folder with yesterday’s date found within the Archive folder located on the Desktop.

You can download it here after unzipping, simply install using terminal with:

sudo chmod a+x desktop-tidy-install.sh
sudo ./desktop-tidy-install.sh

The source code is below:

#!/bin/bash
########################
#
#
# Install script
# For Desktop tidy, compat with any distro running Gnome 3, tested on fedora 20
#
# Adrian callaghan 02-12-2014
#
#
########################


########################
# are you capable?
if [[ $(/usr/bin/id -u) -ne 0 ]]; then
	echo "You must run this install script with super user privileges, use either sudo or become root with su -"
	exit;
fi


########################
# enviroment
user=$SUDO_USER;
userhome="/home/$user";
scriptPath="/usr/local/bin/dt.sh";
autostartFile="dt.desktop";
desktop="$userhome/Desktop";
archive="$desktop/Archived";


########################
# reinstall?
if [ -f "$scriptPath" ] || [ -f "$autostartPath" ]; then
	echo "Removing previous install"
	if [ -f "$scriptPath" ]; then
		rm "$scriptPath"
	fi
	if [ -f "$autostartPath" ]; then
		rm "$autostartPath"
	fi
fi



########################
# create archive folder if none exists, permissions follow later
if [ ! -d "$archive" ]; then
	mkdir "$archive"
fi



########################
# create script
echo "#!/bin/bash" > $scriptPath;
echo "archive=$archive" >> $scriptPath;
echo "desktop=$desktop" >> $scriptPath;
echo 'curr_archive="$archive/$(date +"%d-%B-%Y" -d "1 day ago")";

# if has not been archived yet, archive
if [ ! -d "$curr_archive" ]; then

	mkdir "$curr_archive";

 	for file in $desktop/*; do
		if [ "$file" != "$archive" ]; then
			mv "$file" "$curr_archive"
		fi
	done
fi
' >> $scriptPath;
chmod 755 $scriptPath
chown "$user:$user" $scriptPath



########################
# Add autostart
if [ ! -d "$userhome/.config" ]; then
	mkdir "$userhome/.config"
fi
if [ ! -d "$userhome/.config/autostart" ]; then
	mkdir "$userhome/.config/autostart"
fi
echo "[Desktop Entry]
Name=DeskTidy
GenericName=Creates a daily desktop
Comment=Allows the user to have a clean desktop daily and keep the all the files in an ordered fashion
Exec=$scriptPath
Terminal=true
Type=Application
X-GNOME-Autostart-enabled=true
" > "$userhome/.config/autostart/$autostartFile";
chmod 755 "$userhome/.config/autostart/$autostartFile"
chown "$user:$user" "$userhome/.config/autostart/$autostartFile"



#########################
# Trigger script!
#
source "$scriptPath"
chmod "1775" "-R" "$archive"
chown "root:$user" "-R" "$archive"


#########################
# FEEDBACK
echo "!! Desktop Tidy successfully installed !!"
echo "When you login a desktop will be created based on todays date"
echo "Should you wish to retrieve an old file, archives can be found at $archive and are named by date"
VN:F [1.9.9_1125]
Rating: 10.0/10 (1 vote cast)
VN:F [1.9.9_1125]
Rating: +1 (from 1 vote)
3,479 views

Zend framework 2 restful CMS

August 26th, 2014

Based on ZF2 Skeleton and the Album tutorial, this ZF2 application extends this further by migrating fully to Doctrine2 and adding comments for Albums as an association.

The source code is on GitHub and below is how to set the example up

Dynamic modules

There is provision for Dynamic Modules & layouts, seperating the various layers.

Restful service using put/get/post & delete

The default module has routing setup with a top bar navigation, along with a GUI to demonstrate an AJAX RESTful service.

A RESTful service is in place, that is contained within its own module to serve the Albums and comments objects as Create, Update, Delete and List to the default application.

CMS module

A CMS module is in place that uses identity persistance and Zend Auth to authenticate the users, the login forms and validation are all handled.

The CMS users can be created and managed, the CMS also has independent Navigation from the default route, along with CRUD services for the albums & comments services.

Form validation & Flash Messages

Twitter bootstrap has been intergrated into the CMS, so Flash Messages and form validation are all displaying within a bootstrap enviroment.

HOSTING STRUCTURE

  • Folder structure is /NAMEOFNEWPROJECT/public/
  • Public is the Document-root for the server.
  • Public should not be present prior to cloning from GIT, but setup in the host file
INITIAL SETUP
cd ../NAMEOFNEWPROJECT
git clone https://github.com/adriancallaghan/cmszend2.git NAMEOFNEWPROJECT  (will clone the project into the new project)
cd NAMEOFNEWPROJECT
mv config/autoload/examplelocal.php config/autoload/local.php
nano config/autoload/local.php (set database credientials)
php composer.phar self-update
php composer.phar install
./vendor/bin/doctrine-module orm:schema-tool:create
git remote rm origin
git init
git add *
git commit -m "first commit"
git remote add origin https://github.com/NEW-GIT-REPO-LOCATION.git
git push -u origin master
UPDATE USING GIT/COMPOSER & DOCTRINE2
git pull
php composer.phar install
./vendor/bin/doctrine-module orm:schema-tool:create./vendor/bin/doctrine-module orm:validate-schema
UPDATE DB IF NECESSARY (Caution it can cause the db to flush)
./vendor/bin/doctrine-module orm:schema-tool:update --force
Cms access

You need to add a username, active (true) boolean and (md5) password combination into the cmsuser table in order to be able to login to the cms. The password can be easily md5’d on the cmd line with something like

php -r 'echo md5("SOME PASS");'
VN:F [1.9.9_1125]
Rating: 10.0/10 (1 vote cast)
VN:F [1.9.9_1125]
Rating: +1 (from 1 vote)
9,110 views

Bash script to create virtual hosting in Fedora

August 15th, 2014

I am often needing to add a script to create virtual hosting, below is one I have written for fedora (that can be altered for any distro) that creates the necessary folder structure, vhost host entries and restarts Apache.

#!/bin/bash
 
#################################
# SETTINGS LOCATIONS
WWW_ROOT='/var/www' # no trailing slash
DOC_ROOT='httd_docs' # no trailing slash
 
# SETTINGS TEMPLATE FILE
INDEX_MSG='HOSTING READY FOR &lt;DN&gt;' # &lt;DN&gt; WILL BE REPLACED WITH THE DOMAIN
INDEX_FILE='index.html'
 
# SETTINGS DIRECTORY PERMISSIONS
DIR_OWNER='apache'
DIR_GROUP='apache'
DIR_MOD='770'
 
# APACHE (FEDORA)
APACHE_RELOAD='service httpd restart' # cmd to reload/restart apache
APACHE_CONF_LOCATION='/etc/httpd/conf/httpd.conf' # no trailing slash
APACHE_CONF_TEMPLATE=&quot;
# &lt;FQDN&gt;
&lt;VirtualHost *:80&gt;
    ServerAdmin webmaster@&lt;DN&gt;
    ServerName &lt;FQDN&gt;
    ServerAlias &lt;DN&gt;
 
    DocumentRoot &lt;DN_ROOT&gt;
    ErrorLog /var/log/httpd/&lt;DN_SLUG&gt;-apache-error_log
    CustomLog /var/log/httpd/&lt;DN_SLUG&gt;-access_log common
&lt;/VirtualHost&gt;&quot;; # &lt;DN&gt; WILL BE REPLACED WITH THE DOMAIN, FQDN WITH THE FQDN, DN_SLUG WITH THE DOMAIN SLUG AND DN_ROOT WITH DOCUMENT ROOT
 
# HOSTS FILE
HOSTS_FILE='/etc/hosts'
#################################
 
 
#################################
# FUNCTIONS
function notice() {
        echo &quot;============================================================================================================&quot;
        echo $1
        echo &quot;============================================================================================================&quot;
}
 
function slugify(){
	echo $* | sed 's/^dl-*//ig' | tr '[:punct:]' '-' | tr '[:upper:]' '[:lower:]' | tr -s '[:blank:]' '[\-*]'
}
#################################
 
 
 
#################################
# START
if [[ $(/usr/bin/id -u) -ne 0 ]]; then
	notice &quot;You must be root to run this script&quot;
else
	# GET DN AND FQDN
	notice &quot;Please enter the domain name&quot;
	read DN
	DN=&quot;${DN/#\www./}&quot;
	FQDN=&quot;www.$DN&quot;
 
	# BEGIN 
	host $DN 2&gt;&amp;1 &gt; /dev/null
	if [ ! $? -eq 0 ]; then
		echo &quot;$DN is not valid domain&quot;
	else
		DN_SLUG=$(slugify &quot;$DN&quot;);
		if [ -d &quot;$WWW_ROOT/$DN_SLUG&quot; ]; then
			notice &quot;$DN already exists in $WWW_ROOT/$DN_SLUG&quot;
		else	
			# MAIN STRUCTURE
			mkdir &quot;$WWW_ROOT/$DN_SLUG&quot;
			mkdir &quot;$WWW_ROOT/$DN_SLUG/$DOC_ROOT&quot;
			echo &quot;${INDEX_MSG//&lt;DN&gt;/$FQDN}&quot; &gt; &quot;$WWW_ROOT/$DN_SLUG/$DOC_ROOT/$INDEX_FILE&quot;
 
			# OWNERSHIP
			chown -R &quot;$DIR_OWNER:$DIR_GROUP&quot; &quot;$WWW_ROOT/$DN_SLUG&quot;
			chmod -R &quot;$DIR_MOD&quot; &quot;$WWW_ROOT/$DN_SLUG&quot;
 
			# QUICK LOOK UP LOCALLY
			HOSTS_FILE_BK=&quot;$(date +$HOSTS_FILE-%d%m%Y_%R.bak)&quot;;
			cp &quot;$HOSTS_FILE&quot; &quot;$HOSTS_FILE_BK&quot;;
			if [ ! -f &quot;$HOSTS_FILE_BK&quot; ]; then
				notice &quot;Failed to create host file backup at $HOSTS_FILE_BK&quot;
			else 
 
				echo &quot;# ${FQDN}&quot; &gt;&gt; &quot;$HOSTS_FILE&quot;;
				echo 127.0.0.1   ${DN} &gt;&gt; &quot;$HOSTS_FILE&quot;;
				echo 127.0.0.1   ${FQDN} &gt;&gt; &quot;&quot;$HOSTS_FILE&quot;&quot;;
 
				# APACHE ENTRIES
				APACHE_TEMPLATE=&quot;${APACHE_CONF_TEMPLATE//&lt;DN&gt;/$DN}&quot;;
				APACHE_TEMPLATE=&quot;${APACHE_TEMPLATE//&lt;FQDN&gt;/$FQDN}&quot;;
				APACHE_TEMPLATE=&quot;${APACHE_TEMPLATE//&lt;DN_ROOT&gt;/$WWW_ROOT/$DN_SLUG/$DOC_ROOT/}&quot;;
				APACHE_TEMPLATE=&quot;${APACHE_TEMPLATE//&lt;DN_SLUG&gt;/$DN_SLUG}&quot;;
				APACHE_CONF_LOCATION_BK=&quot;$(date +$APACHE_CONF_LOCATION-%d%m%Y_%R.bak)&quot;;
				cp &quot;$APACHE_CONF_LOCATION&quot; &quot;$APACHE_CONF_LOCATION_BK&quot;;
				if [ -f &quot;$APACHE_CONF_LOCATION_BK&quot; ]; then
					echo &quot;$APACHE_TEMPLATE&quot; &gt;&gt; $APACHE_CONF_LOCATION;
					$APACHE_RELOAD;
					notice &quot;$DN created at $WWW_ROOT/$DN_SLUG (apache bkup file found at $APACHE_CONF_LOCATION_BK)&quot;
				else
					notice &quot;Failed to create Apache config backup at $APACHE_CONF_LOCATION_BK&quot;
				fi	
			fi
		fi
	fi
 
fi
read STOP
exit;
################################
VN:F [1.9.9_1125]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.9_1125]
Rating: 0 (from 0 votes)
16,188 views

ZF2 different layouts in modules

June 4th, 2013

To enable a different layout in a module, to your module.php for the module define a new layout like so

public function init(ModuleManager $mm)
    {
        $mm->getEventManager()->getSharedManager()->attach(__NAMESPACE__, 'dispatch', function($e) {
            $e->getTarget()->layout('admin/layout');
        });
    }

then within your module.config.php view_manager settings define the template

'view_manager' => array(
        'template_map' => array(
            'admin/layout'           => __DIR__ . '/../view/layout/cms.phtml',
        ),
        'template_path_stack' => array(
            __DIR__ . '/../view',
        ),
    ),

or you can define a direct path in your module.php without any template mapping i.e

public function init(ModuleManager $mm)
    {
        $mm->getEventManager()->getSharedManager()->attach(__NAMESPACE__, 'dispatch', function($e) {
            $e->getTarget()->layout('layout/admin');
        });
    }

This will load module/view/layout/admin.phtml when this module is run

VN:F [1.9.9_1125]
Rating: 6.1/10 (8 votes cast)
VN:F [1.9.9_1125]
Rating: +2 (from 4 votes)
16,435 views

Galaxy S3 no internet on virgin media super hub

March 17th, 2013

Samsung galaxy S3 will not connect to virgin media super hub can be a problem, I found mine would connect but had no internet – and everything else on the network did.

After several hours of looking through forums, rebooting and changing settings, I found the issue to be with the hub itself, for some reason in Advanced-settings>DHCP>DHCP Reservation I found the mobile was being addressed on a strange IP like 10.125.x.x.x and not the one it had been allocated by DHCP.

I took note of the mac and device name in the IP Lease table, switched off the WIFI on the mobile (disconnecting it from the router), hit refresh to make sure it was no longer listed in the IP lease table.

Next I added a reservation entry to the the lease table for the device, using its mac and device name, and bound it to an IP that was not being used.

Voila.. Internet on the S3

VN:F [1.9.9_1125]
Rating: 8.0/10 (2 votes cast)
VN:F [1.9.9_1125]
Rating: +1 (from 3 votes)
12,808 views

Remote controlling Tivo

October 21st, 2012

I was interested in what my ethernet port was doing on my virgin media TIVO box, so I ran some tests and found I could control my TIVO box from my laptop, here are my findings.

First, I went into the Tivo boxes settings on screen and enabled network access.

Next, I logged into my home hub/router to find out what IP address it had been allocated
http://192.168.100.1/ and clicked devices.

Once I had its IP address, (192.168.0.7) I scanned its ports and found the following services:

adrian@adrian-laptop:~$ nmap 192.168.0.7
 
Starting Nmap 5.00 ( http://nmap.org ) at 2012-10-21 10:37 BST
Interesting ports on 192.168.0.7:
Not shown: 997 filtered ports
PORT     STATE SERVICE
443/tcp  open  https
2190/tcp open  unknown
2191/tcp open  unknown
 
Nmap done: 1 IP address (1 host up) scanned in 5.50 seconds

The obvious one that stands out is port 443, so visiting https://192.168.0.7/ shows a web server requesting login, I found that the username is tivo and the password is your media key found in settings > mediakey.

Once logged in, a list of recorded programmes will be displayed but however streaming and downloading are disabled :(.

I tried for sometime to circumvent the streaming restriction using various techniques the closest I came was with VLC and special plugins http://tivo-vlc.sourceforge.net/notes.php#install, but so far I haven’t been able to achieve this.

I looked into what the box is, and it turns out its fundamentally Linux box with a glossy coat, with some features disabled (like streaming something to do with UK copyright laws).

Along the way I found I could telnet to port 31339 on the box

telnet 192.168.0.7 31339

which responded with

CH_STATUS 0213 RECORDING

This is the status of the two tuners, and what they are doing, you can now use commands like:

Code:

KEYBOARD (Dunno what this does)

TELEPORT <PLACE>- e.g TIVO, LIVETV, GUIDE, and NOWPLAYING.

SETCH <CHANNEL> - Change channel. If the current tuner is recording a program, it will change the other tuner. If both tuners are recording, the TiVo will respond with "CH_FAILED RECORDING <Title>. Using this command while Tivo is replaying will give "CH_FAILED NO_LIVE".

FORCECH <CHANNEL> - This command will force the current tuner to the tune the desired channel regardless of what it's doing. If a recording is being recorded it will cancel the recording and change the channel without confirmation.

Also a complete set of IRCODE’s exist

Code:

IRCODE <COMMAND>

a quick google and I found the following IRCODE commands that seem to work.

UP
DOWN
LEFT
RIGHT
SELECT
TIVO
LIVETV
THUMBSUP
THUMBSDOWN
CHANNELUP
CHANNELDOWN
RECORD
DISPLAY
DIRECTV
NUM0
NUM1
NUM2
NUM3
NUM4
NUM5
NUM6
NUM7
NUM8
NUM9
ENTER
CLEAR
PLAY
PAUSE
SLOW
FORWARD
REVERSE
STANDBY
NOWSHOWING
REPLAY
ADVANCE
DELIMITER
GUIDE

Typing these commands into the telnet session, made the tivo box change channel etc…. cool!

To exit the telnet session press

Code:

CTRL + ]

thats right, control and right square bracket!!, then type quit at the prompt

I was able to source a nice GUI that can automate these commands https://github.com/wmcbrine/tivoremote

So, as long as you have Python installed (Mac & linux users by default), just running the script produces a nice GUI that can manage your Tivo box from your laptop.

I also found, if your interested in developing apps for it, its SDK is written for AS3 and can be found here http://developer.tivo.com/

VN:D [1.9.9_1125]
Rating: 8.1/10 (9 votes cast)
VN:D [1.9.9_1125]
Rating: +3 (from 5 votes)
35,641 views

form to database php

October 15th, 2012

I have written a collection of classes, that are capable of accepting a submission from a get (REST) or post (form) and output them to an email, the screen or to a database table.

The class can be used to output a CSV, an email or XML (REST).

The code is very straight forward for example create a form.html and add the following.

<form method="post" action="save.php">
  <label for="firstname">Firstname</label>
  <input type="text" name="firstname" id="firstname"><br>
  <label for="surname">Surname</label>
  <input type="text" name="surname" id="surname"><br>
  <input type="submit" value="Submit">
</form>

This form will submit to save.php, we need to now create this, create the file save.php and add the following

require_once('classes.php'); // load the classes

This loads the classes, and is required to make this work, next

        listener::getInstance();

Gets an instance of the listener, the listener has the responsibility of handling the data, it sets a number of values by default, one of which is the default submission type (GET) this needs to be changed to POST, so

        listener::getInstance()->method('POST');

Next, the listener needs to know which fields are valid fields, otherwise every bit of junk somebody sends to this script will be placed into the database, this is done in the form of an array, with the array key being the fieldname, and the value being whether or not is it required, if a field is defined as required and not codesent, the submission will fail with an error.

array(
    'firstname'=>true
    'surname'=>true
)

tell the listener about these fields

        listener::getInstance()
                ->method('POST')
                ->setFields(
                        array(
                            'firstname'=>true
                            'surname'=>true
                            )
                        );

next we have to define, what we wish to do with the submission, in this case, save it to a database, first get the database instance.

database::getInstance();

by default, the database will default to certain values, typically it will connect with the username “root”, password “”, database “data”, host “localhost”, table called “submissions” and the field “submitted”.
if you need to change any of these values, it can be done by setting a config of type stdConfig with an array of new parameters.
If you do not decalre say a username, it just defaults, the avaialble fields are: username, password, database, table, field and host

database::getInstance()->setConfig(
                        database::stdConfig(
                                array(
                                    'password'=>'1234'
                                    )
                                )
);

The database instance is placed in setAction like this:

        listener::getInstance()
                ->method('POST')
                ->setFields(
                        array(
                            'firstname'=>true
                            'surname'=>true
                            )
                        )
                ->setAction(
                    database::getInstance()->setConfig(
                        database::stdConfig(
                                array(
                                    'password'=>'1234'
                                    )
                                )
                    )
                );

Next we need some sort of feedback, about whether or not it was successful, this can be done by asking the instance what happened, for example:

// some visual feedback
if (listener::getInstance()->success){
     echo 'Thankyou!';
} else {
     echo 'The following problems were encountered';
     print_r(listener::getInstance()->errors);
}

Lets put it all together!, complete code below:

 
        require_once('classes.php'); // load the classes
 
        listener::getInstance()
                ->method('POST')
                ->setFields(
                        array(
                            'firstname'=>true
                            'surname'=>true
                            )
                        )
                ->setAction(
                    database::getInstance()->setConfig(
                        database::stdConfig(
                                array(
                                    'password'=>'1234'
                                    )
                                )
                    )
                );
 
// some visual feedback
if (listener::getInstance()->success){
     echo 'Thankyou!';
} else {
     echo 'The following problems were encountered';
     print_r(listener::getInstance()->errors);
}

You will need the class library found in here (right click save as)

Should you require a REST service, a wrapper is included to output the response as xml, for example:

<?php
require_once('classes.php'); // load the classes
 
Output::toXml(
        listener::getInstance()
                ->setFields(
                        array(
                            'bob'=>true
                            )
                        )
                ->setAction(
                    database::getInstance()->setConfig(
                        database::stdConfig(
                                array(
                                    'password'=>'1234'
                                    )
                                )
                    )
                )
            );
 
//foreach(listener::getInstance()->errors AS $err) echo $err;

to get the submissions as a Csv, similiarly:

<?php
require_once('classes.php'); // load the classes
 
Output::toCsv(
        database::getInstance()->setConfig(
            database::stdConfig(array('password'=>'1234'))
            )->fetchAll()
        );
 
//echo database::getInstance()->error;

A rest Example can be found here, along with the ability to CSV export

VN:F [1.9.9_1125]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.9_1125]
Rating: 0 (from 0 votes)
7,600 views

thickdialog

June 20th, 2012 Jquery dialog can be made to work as a either an ajax form, a dialog box or confirmation box just by use of a class similair to the way in which thickbox used to work (the examples work perfectly outside of wordpress).

ThickDialog examples

Download

Simple thickbox style popup

Popup example
code:

<a href="/demos/thickdialog/popup.html" title="A pop up" class="dialog-box">Popup example</a>

usage: add the class “dialog-box” to make this work

Simple thickbox style confirmation box

Confirm example
code:

<a href="/demos/thickdialog/delete.html" title="Are you sure?" class="dialog-confirm">Confirm example</a>

usage: add the class “dialog-confirm” to make this work

Simple thickbox style form submission

Form example
code:

<a href="/demos/thickdialog/form.php" title="Please complete" class="dialog-confirm">Form example</a>

usage: add the class “dialog-form” to make this work

VN:F [1.9.9_1125]
Rating: 10.0/10 (1 vote cast)
VN:F [1.9.9_1125]
Rating: +1 (from 1 vote)
4,999 views

jquery ui ajax form thickbox

June 20th, 2012 Jquery dialog can be made to work as a ajax form in a similair way to thickbox.

The link to the form (such as registration form), can be made to load inside a popup, and loaded using ajax by simply adding a class to the href.

For example this link could perform a registration, just like thickbox used to behave adding the class ‘dialog-form’ (the title is used to title the form popup) loading the content on submission.

<a href="/demos/thickdialog/form.php" class="dialog-form" title="Register">register</a>

Example: register

In order to do this you will need Jquery, and Jquery-UI and the code below.

Alternatively I have written a library called thickdialog which supports the form, confirmation box and pop ups just by adding a simple class, which is compatible with any framework and can be downloaded from there.

// form pop ups, just give an anchor point the class dialog_form, and the title will be used as the title 
$(function (){
 
    function submitBind(layout,original_url){
 
        $(layout).find('form').submit(function(event){
 
            /* stop form from submitting normally */
            event.preventDefault(); 
 
            url = $(this).attr('action')=='' ? original_url : $(this).attr('action');                    
 
            /* Send the data using post and put the results in a div */
            $.post(
                url,
                $(this).serialize(),
                function(data) {
 
                    $('#dialog').empty();
                    $('#dialog').append(data);
                    $('#dialog').dialog('option', 'position', 'center');
                    submitBind(layout, original_url);
                });
 
        }); 
 
    }
 
 
    $('a.dialog-form').click(function() {
 
        var original_url = this.href;
        var title = this.title;
        // show a spinner or something via css
        var dialog = $('<div id="dialog" style="display:none" class="loading">Loading</div>').appendTo('body');
        // open the dialog
        dialog.dialog({
 
            width: dialogBox_width,
 
            // add a close listener to prevent adding multiple divs to the document
            close: function(event, ui) {
                // remove div with all data and events
                dialog.remove();
            },
            modal: true
        });
 
        // load remote content
 
        dialog.load(
            original_url,
            function (responseText, textStatus, XMLHttpRequest) {
                // remove the loading class
                dialog.removeClass('loading');
                dialog.dialog('option', 'position', 'center');
                dialog.dialog('option', 'title', title);
 
                submitBind(this,original_url);
 
            }
        );
        //prevent the browser to follow the link
        return false;
    });
});
VN:F [1.9.9_1125]
Rating: 6.0/10 (4 votes cast)
VN:F [1.9.9_1125]
Rating: -2 (from 2 votes)
9,661 views

jquery confirmation box thickbox

June 20th, 2012 Jquery dialog can be made to work as a confirmation box in a similair way to thickbox.

The link to the action (such as deletion), can be made to display a confirmation box before it completes, by simply adding a class to the href.

For example this link could perform a deletion, just like thickbox used to behave adding the class ‘dialog-confirm’ (the title is used to title the dialog confirm) will request the user to confrim firstly.

<a href="/demos/thickdialog/delete.php" class="dialog-confirm" title="Are you sure about this?">delete</a>

Example: delete(example works fine outside of wordpress)

In order to do this you will need Jquery, and Jquery-UI and the code below.

Alternatively I have written a library called thickdialog which supports the confirmation box, pop ups and forms just by adding a simple class, which is compatible with any framework and can be downloaded from there.

// confirm box, add the class dialog-confirm and a title and it does the rest
$(function (){
    $('a.dialog-confirm').click(function() {
 
        var url = this.href;
        var dialog = $('<div id="dialog" style="display:none" title="Are you sure?">'+this.title+'</div>').appendTo('body');
 
        dialog.dialog({
            resizable: false,
            height:confirmBox_height,
            modal: true,
 
            buttons: {
                    "Yes": function() {
                            $(this).dialog( "close" );
                            window.location.href = url;
 
                    },
                    "No": function() {
                            $(this).dialog( "close" );
                    }
            }
        });
 
        dialog.dialog('option', 'position', 'center');
 
        //prevent the browser to follow the link
        return false;
    });
});
VN:F [1.9.9_1125]
Rating: 8.0/10 (1 vote cast)
VN:F [1.9.9_1125]
Rating: +2 (from 2 votes)
6,083 views

Jquery dialog thickbox

June 20th, 2012 Jquery dialog can be made to work in a similair way to thickbox.

Any link to content, can have its content loaded into a jquery dialog box, by simply adding a class to the href.

For example this standard page can be made to behave like a thickbox pop-up by adding the class ‘dialog-box’ (the title is used to title the dialog box).

<a href="/demos/thickdialog/page.php" class="dialog-box" title="popup">popup</a>

Example: popup (example works fine outside of wordpress)

In order to do this you will need Jquery, and Jquery-UI and the code below.

Alternatively I have written a library called thickdialog which supports the popups, confirmation boxes and forms just by adding a simple class, which is compatible with any framework and can be downloaded from there.

// pop ups, just give an anchor point the class dialog_box, and the title will be used as the title 
$(function (){
    $('a.dialog-box').click(function() {
        var url = this.href;
        var title = this.title;
        // show a spinner or something via css
        var dialog = $('<div id="dialog" style="display:none" class="loading">Loading</div>').appendTo('body');
        // open the dialog
        dialog.dialog({
 
            width: dialogBox_width,
 
            // add a close listener to prevent adding multiple divs to the document
            close: function(event, ui) {
                // remove div with all data and events
                dialog.remove();
            },
            modal: true
        });
 
        // load remote content
        dialog.load(
            url, 
            {}, // omit this param object to issue a GET request instead a POST request, otherwise you may provide post parameters within the object
            function (responseText, textStatus, XMLHttpRequest) {
                // remove the loading class
                dialog.removeClass('loading');
                dialog.dialog('option', 'position', 'center');
                dialog.dialog('option', 'title', title);
 
            }
        );
        //prevent the browser to follow the link
        return false;
    });
});
VN:F [1.9.9_1125]
Rating: 7.0/10 (3 votes cast)
VN:F [1.9.9_1125]
Rating: 0 (from 0 votes)
10,700 views

javascript image rotation

January 9th, 2012

Very simple class that rotates images on any event, on any target element (with a preloader).

Click here for an example.

To use it yourself (how the example works):

1. include jquery and the class

<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="galleryRotate.js"></script>

2. Instantiate the class with an array of images

$images = ['1.jpg','2.jpg','3.jpg'];
var rotator = new GalleryRotate($images);

3. bind the objects change method to an event, such as mouseclick, telling it the name of target element (always done once the webpage is ready)

$(document).ready(function(){
 
	// click the image
	$('#button').click(function(){
		return rotator.change('#img');
	});
});

Once again an example can be found here.

The full source code can be downloaded here.

The class code is very straight forward and below for completeness.

function GalleryRotate ($images){  
 
	this.preload = function () {
	    $(this.images).each(function(){
	        $('<img/>')[0].src = this;
	    });
	}
 
	this.change = function($element){
 
		$img = this.images[this.imgNo];
 
		if ($element){
			$($element).attr("src", $img);
		}
		else alert($img);
 
		this.imgNo++;
 
		if (this.imgNo==this.images.length){
			this.imgNo=0;
		}
 
		return false;
	}
 
	this.init = function ($images) {
		this.images = $images;
		this.imgNo=0;
		this.preload();	
	}
 
	this.init($images);
}
VN:F [1.9.9_1125]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.9_1125]
Rating: 0 (from 0 votes)
4,845 views