Robert Sandiford

PHP Developer

07864 820151 / 07487409249

mail@robertsandiford.co.uk

Code Samples



A Command, in Laravel


<?php

	use Illuminate\Console\Command;
	use Symfony\Component\Console\Input\InputOption;
	use Symfony\Component\Console\Input\InputArgument;
	 
	class RunTransferCommand extends Command {
	 
	    /**
	     * The console command name.
	     *
	     * @var string
	     */
	    protected $name = 'runTransfer';
	 
	    /**
	     * The console command description.
	     *
	     * @var string
	     */
	    protected $description = "Run a Transfer";
	 
	     /**
	     * The scope variable passed to sub-scripts for data transport
	     *
	     * @var array
	     */
	    protected $scope = [];
	     /**
	     * Get the console command arguments.
	     *
	     * @return array
	     */
	    protected function getArguments()
	    {
	        return [];
	    }
	 
	    /**
	     * Get the console command options.
	     *
	     * @return array
	     */
	    protected function getOptions()
	    {
	        return [
	            ['groupid',  null, InputOption::VALUE_OPTIONAL, 'Group ID, or IDs to transfer', ''],
	            ['module',   null, InputOption::VALUE_OPTIONAL, 'Modules to transfer', null],
	            ['patch',    null, InputOption::VALUE_OPTIONAL, 'Modules to transfer', null],
	            ['action',   null, InputOption::VALUE_OPTIONAL, 'Action to perform', ''],
	            ['database', null, InputOption::VALUE_OPTIONAL, 'Data to transfer the data /to/', 'b'],
	        ];
	    }

	    public function setConfigs()
	    {

	        // group and association id
	        if ( strcasecmp( $this->option('groupid'), "all" ) === 0 ) {

	            Config::set('transfer.included_groups', Config::get('transfer.transferable_groups'));
	            Config::set('transfer.included_associations', Config::get('transfer.transferable_associations'));

	        } else if ( ! empty( $this->option('groupid') )) {

	            $group_id = explode(',', $this->option('groupid'));
	            $association_id = \Transfer::getAssociationIds($group_id);

	            Config::set('transfer.included_groups', $group_id);
	            Config::set('transfer.included_associations', $association_id);

	        } else {

	            $group_id = array_diff(Config::get('transfer.transferable_groups'), Config::get('transfer.gone_live_groups'));
	            $association_id = \Transfer::getAssociationIds($group_id);

	            Config::set('transfer.included_groups', $group_id);
	            Config::set('transfer.included_associations', $association_id);

	        }

	        $this->line("group id:");
	        $this->line(Config::get('transfer.included_groups'));
	        $this->line("association_id:");
	        $this->line(Config::get('transfer.included_associations'));

	        // database
	        Config::set('database.default', $this->option('database'));

	        $this->line("database:");
	        $this->line(Config::get('database.default'));

	        // modules
	        //$this->modules = ($this->option('module')) ? array_map(function($module){ return ucwords($module); }, explode(',', $this->option('module')) : ['Support', 'Disability'];
	        //$this->modules = array_map(function($module){ return ucwords($module); }, $this->modules);

	        $this->modules = ($this->option('module'))
	            ? array_map(function($module){ return ucwords($module); }, explode(',', $this->option('module')))
	            : ( ( ! $this->option('patch')) ? ['Support', 'Disability'] : [] );

	        $this->line("modules:");
	        $this->line($this->modules);

	        $this->patches = ($this->option('patch'))
	            ? array_map(function($patch){ return ucwords($patch); }, explode(',', $this->option('patch')))
	            : [];

	        $this->line("patches:");
	        $this->line($this->patches);
	    }

	    /**
	     * Execute the console command.
	     *
	     * @return void
	     */
	    public function fire()
	    {

	        $this->setConfigs();

	        foreach($this->modules as $module){
	            $module = "\\Transfers\\Modules\\{$module}";
	            (new $module)->run($this->scope);
	        }  

	        foreach($this->patches as $patch){
	            $patch = "\\Transfers\\Patches\\{$patch}";
	            (new $patch)->run($this->scope);
	        }  

	        $this->info('Done.');

	    }
	 
	}
		

Data Transfer Script, in Laravel


<?php
	namespace Transfers\Support;

	class Programme extends \Transfers\BaseTransfer {

	    public function run()
	    {

	        $users = \User::mapped();

	        $this->insertRecords(
	            
	            // The model of the destination table
	            (new \SupportModuleProgramme),

	            // The record set from the legacy database
	            \Models\Legacy\Project::with( 'landlord', 'projectTheme', 'projectLeader', 'closedBy' )->includeAssociations()->get(), 
	            
	            // The callback function to insert a row
	            function($project, $inserts) use ($users) {
	                
	                if ($this->checkGroupAndLandlord($project->landlord->AssociationID, $project->LandlordID, $groupId, $landlordId)) {

	                    $reference = \Models\Legacy\Project::reference($project->Reference, $project->StartDate, $project->EndDate, $project->projectTheme->Name, $project->Title);

	                    return [
	                        'id'                  => $project->ID,
	                        'programme_theme_id'  => $project->ProjectThemeID,
	                        'reference_part_one'  => $reference->reference_part_one,
	                        'reference_part_two'  => $reference->reference_part_two,
	                        'name'                => $project->Title,
	                        'started_at'          => parseDate($project->StartDate),
	                        'ended_at'            => parseDate($project->EndDate),
	                        'programme_leader_id' => $project->projectLeaderID /*$users[$groupId][trim(strtolower( $project->projectLeader->Name ))]*/,
	                        'notes'               => $project->Purpose,
	                        'group_id'            => $groupId,
	                        'landlord_id'         => $landlordId,
	                        'created_by'          => \Config::get('transfer.cr_user'),
	                        'created_at'          => null,
	                        'updated_at'          => null,
	                        'deleted_at'          => parseDate($project->ClosedDate),
	                        'deleted_by'          => $project->closedBy->ID ?: null
	                    ];

	                }

	            }

	        );

	        return $view;
	    }

	}
		

And the base class behind it


<?php

	namespace Transfers;

	class BaseTransfer {

	    protected $inserts = array();

	    protected $view = "";

	    /** 
	     *  Sets the total number of records that are about to be transferred
	     *
	     *  Used to display progress percentages
	     */
	    protected function setTotal($total)
	    {
	        $this->total = $total;
	    }

	    /** 
	     *  Loops through records returned from a query, and runs the callback with makes the inserts array
	     */
	    protected function insertRecords($model, $records, $insertRecordCallback, $truncate = true)
	    {
	        
	        if ($truncate) {

	            $oldRecords = $model;

	            if ( array_key_exists('min', (array) $truncate) and array_key_exists('max', (array) $truncate) ) {

	                if ( ! $truncate['min'] or ! $truncate['max']) throw new \Exception('Min or Max not setting when trying to delete within id range');
	                $oldRecords = $oldRecords->where('id', '>=', $truncate['min'])->where('id', '<=', $truncate['max']);

	            } else {

	                if ( ! $model->minNewDataId ) throw new \Exception('Minimum ID has not been set in ' . get_class($model));
	                $oldRecords = $oldRecords->where('id', '<', $model->minNewDataId);

	            }

	            if ( $truncate['deleteByGroup'] ) {

	                if ( ! \Config::get('transfer.included_groups') ) throw new \Exception('transfer.included_groups not set when trying to delete rows for group');
	                $oldRecords = $oldRecords->whereIn('group_id', \Config::get('transfer.included_groups'));

	            }

	            $oldRecords->delete();
	        }

	        $inserts = [];

	        $i = 1; $lastRecord = $records->last();
	        foreach ($records as $record) {
	        
	            if ($insert = $insertRecordCallback($record, $inserts)) {
	                if (is_array(reset($insert))) {
	                    $inserts = array_merge($inserts, $insert);
	                } else {
	                    $inserts[] = $insert;
	                }
	            }

	            // insert every 1000 records, or on the final record
	            if ( $i % 1000 == 0 or $record->ID == $lastRecord->ID ) {

	                messageDump($inserts);

	                if ( ! ($model->insert($inserts))) message('Not inserted in batch (this means these should be inserted individually inside the callback)');

	                $inserts = null;
	            }

	            $i++;

	        }

	    }

	    /** 
	     *  A helper for InsertRecords
	     */
	    protected function insertRecordsNice($arguments)
	    {

	        $model                = $arguments['destination_model'];
	        $records              = $arguments['record_set'];
	        $insertCallback       = $arguments['insert_callback'];

	        $this->insertRecords($model, $records, $insertCallback);

	    }

	    protected function checkGroupAndLandlord($associationId, $oldLandlordId, &$groupId, &$landlordId)
	    {

	        $groupId    = \Transfer::getGroup($associationId);
	        $landlordId = \Transfer::getLandlord($associationId, $oldLandlordId);

	        if ( is_numeric($groupId) and is_numeric($landlordId) ) return true;

	        else return false;

	    }
	}
		

Some Blade, in Laravel


@include('snippets.begin')

    <div class="page container">

        <div class="row top">
            <ul class="right">
                @if(Auth::check())
                    <li class="{{ (strpos(URL::current(), URL::to('admin/dashboard')) !== false) ? 'active' : '' }}">
                        {{HTML::link('admin/dashboard','Dashboard')}}
                    </li>
                    <li class="{{ (strpos(URL::current(), URL::to('logout'))!== false) ? 'active' : '' }}" >
                        {{HTML::link('logout','Logout')}}
                    </li>
                @else
                    <li class="{{ (strpos(URL::current(), URL::to('login'))!== false) ? 'active' : '' }}">
                        {{HTML::link('login','Login')}}
                    </li>
                @endif
            </ul>
        </div>

        @include('snippets.me')

        <br /><br />
        
        <div class="row">
            <div class="col-md-8 col-sm-8">

                <article class="post clear">
                    <header class="post-header">
                        <h1 class="post-title">
                            {{ e($post->title) }}
                        </h1>
                    </header>
                    <div class="post-content">
                        <p>{{ nl2br(e($post->content)) }}</p>
                    </div>
                    <footer class="post-footer">
                        <div class="clearfix">
                            <span class="right date">{{ $post->present('createdDate') }}</span>
                        </div>
                    </footer>
                </article>

                @if(isset($previousPost))
                    <span class="left">{{HTML::linkRoute('post.show','previous post "' .$previousPost->title . '"',$previousPost->id)}}</span>
                @endif
                @if(isset($nextPost))
                    <span class="right">{{HTML::linkRoute('post.show','next post "' .$nextPost->title . '"',$nextPost->id)}}</span>
                @endif
            </div>
        </div>

    </div>

@include('snippets.end')
		

Tests


<?php
	require_once('global.php');
	require_once('TestBase.php');

	class DatabaseFieldDuplicatesTest extends TestBase {

	    public $title = "Database Field Duplicates Test";

	    public function __construct($db = null) {
	        parent::__construct();

	        $this->configuration = (object) array('database_field', 'database_field_option');

	        $this->setup($db);
	    }

	    public function TestThereAreNoDuplicatesInTransferredData() {

	        message("There should be no Database Field Duplicates In Transferred Data");

	        $activity_participant_duplicates = $this->connDest->query("SELECT COUNT(*) FROM database_field f WHERE id < 1000000 AND EXISTS (SELECT id FROM database_field g WHERE f.id != g.id AND f.group_id = g.group_id AND f.system_name = g.system_name AND g.id < 1000000)")->fetchColumn();

	        message("Database Field Duplicate In Transferred Data: {$activity_participant_duplicates}");

	        $this->Assert($activity_participant_duplicates == 0, 'Database Field Duplicates In Transferred Data Should Be 0');

	    }

	    public function TestThereAreNoDuplicatesInTransferredDataAgainstLiveData() {

	        message("There should be no Database Field Duplicates In Transferred Data Against Live data");

	        $activity_participant_duplicates = $this->connDest->query("SELECT COUNT(*) FROM database_field f WHERE id < 1000000 AND EXISTS (SELECT id FROM database_field g WHERE f.id != g.id AND f.group_id = g.group_id AND f.system_name = g.system_name)")->fetchColumn();

	        message("Database Field Duplicates In Transferred Data Against Live data: {$activity_participant_duplicates}");

	        $this->Assert($activity_participant_duplicates == 0, 'Database Field Duplicates In Transferred Data Against Live data Should Be 0');

	    }

	    public function TestThereAreNoDuplicatesInAllData() {

	        message("There should be no Database Field Duplicates In All Data");

	        $activity_participant_duplicates = $this->connDest->query("SELECT COUNT(*) FROM database_field f WHERE EXISTS (SELECT id FROM database_field g WHERE f.id != g.id AND f.group_id = g.group_id AND f.system_name = g.system_name)")->fetchColumn();

	        message("Database Field Duplicates In All Data: {$activity_participant_duplicates}");

	        $this->Assert($activity_participant_duplicates == 0, 'Database Field Duplicates In All Data Should Be 0');

	    }

	}
		

And the base class behind it


<?php
	require_once('global.php');

	class TestBase {

	    public $configuration;
	    public $connDest;
	    public $assertions = 0;
	    public $assertionsPassed = 0;
	    public $assertionsFailed = 0;

	    public function __construct() {
	        $this->configuration = new StdClass;
	    }

	    public function Setup($db = null) {
	        global $connDEMO, $connSTAG, $connTEST, $connB;

	        switch($db) {
	            case 'stag':
	                $db = $connSTAG;
	                break;

	            case 'demo':
	                $db = $connDEMO;
	                break;

	            case 'test':
	                $db = $connTEST;
	                break;

	            case 'transfer':
	                $db = $connB;
	                break;

	            default:
	                $db = $connSTAG;
	        }

	        $this->configuration->connDest = $db;

	        $this->SetupDatabase(/*$this->configuration->connSource, $this->configuration->connDest, $this->configuration->tables*/);
	    }

	    public function SetupDatabase(/*$connSource, $connDest, $tables*/) {
	        // set up a target database
	        $this->connDest = $this->configuration->connDest;
	        $databaseDest   = $this->connDest->query("SELECT DATABASE()")->fetchColumn(0);
	        message("Using Database {$databaseDest}", false, array('white', 'black'));
	    }

	    public function Assert($assertion, $message) {
	        $this->assertions++;
	        if ($assertion) {
	            $this->assertionsPassed++;
	        } else {
	            $this->assertionsFailed++;
	            message("Assertion Failed: " . $message, false, array('white', 'red'));
	        }
	    }

	    public function RunTests() {
	        $methods = get_class_methods(get_class($this));
	        $i = 0;
	        foreach ($methods as $method) {
	            if (substr($method, 0, 4) == 'Test') {
	                $this->RunTest($method);
	                $i++;
	            }
	        }
	        if ($i) message("$i tests run");
	    }

	    public function RunTest($method) {

	        $this->assertions = $this->assertionsPassed = $this->assertionsFailed = 0;

	        $this->$method();

	        if ($this->assertionsPassed > 0 and $this->assertionsFailed == 0) {
	            message("Test Run. {$this->assertions} Assertions. All Ok.", true, array('white', 'green'));
	        } else if ($this->assertionsFailed > 0) {
	            message("Test Run. {$this->assertions} Assertions. $this->assertionsPassed Passed. $this->assertionsFailed Failed.", true, array('white', 'red'));
	        } else {
	            message("Test Run. No Assertions.", true, array('white', 'black'));
	        }
	        message("");

	    }

	}