How to improve deeply flawed one-year-old SimCity 5

I was exposed to the SimCity franchise at the beginning, when SimCity boasted a 2D top-down view with zoning represented by green, blue, and yellow squares with a letter centered in the middle of the shape. I watched the simulation game evolve into a 3D landscape with farms and waste added in SimCity 3000, and regional play added in SimCity 4. Every release of SimCity was marked by critical acclaim from professionals and gamers alike. This history leaves SimCity with a special place in my heart. It is one of the few games that has stood the test of time through iterations of DOS, Windows 3.1, and Windows XP, not to mention a few consoles along the way.

The fifth iteration of the SimCity franchise, which is plainly titled “SimCity,” has failed to live up to the franchise’s history of critical acclaim, even after a year of bug fixes. While the game is certainly playable, no longer are the days of long-term engagements or even true cities. The Great Works feature in SimCity 5 is still exceptionally buggy and the agent system boated by Maxis has been an utter failure in terms of performance as well as artificial intelligence. Continue reading

Unit testing multiple ZF2 modules at once

Although it’s been over a year since the release of Zend Framework 2, I have yet to see compelling documentation on how to execute unit tests for an entire application.  If you are using Zend Studio 10, the default ZF2 module template provides testing architecture that is largely incompatible with multi-module testing.

Setup testing architecture

First, create a tests directory in your ZF2 application root.

cd /home/zf2-app
mkdir tests

PHPUnit configuration

After that, create the following PHPUnit XML configuration file in the newly-created tests directory. To add code coverage, simply add a logging entry to the XML file. Depending on how you run the tests, this allows code coverage for the entire application in one report, or a module-specific code coverage report.

<phpunit bootstrap="Bootstrap.php" backupGlobals="false">
    <testsuites>
        <testsuite name="application">
            <directory>../module/Application</directory>
        </testsuite>
        <testsuite name="anothermodule">
            <directory>../module/AnotherModule</directory>
        </testsuite>
    </testsuites>
    <filter>
        <whitelist>
            <directory suffix=".php">../module</directory>
            <exclude>
                <directory suffix=".php">../module/*/tests</directory>
            </exclude>
        </whitelist>
    </filter>
</phpunit>

Bootstrapping

Next, you’ll need to create the Bootstrap.php file referenced in the PHPUnit configuration. In this case, the bootstrap will load and setup the application configuration file and load the specified modules. It is remarkably similar to the initialization process used when running the application in a normal context.

<?php

use ZendServiceManagerServiceManager;
use ZendMvcServiceServiceManagerConfig;

chdir(dirname(__DIR__));

include_once 'init_autoloader.php';

$testsPath = __DIR__;
if (is_readable($testsPath . '/TestConfiguration.php')) {
    require_once $testsPath . '/TestConfiguration.php';
} else {
    require_once $testsPath . '/TestConfiguration.php.dist';
}

$configuration = include 'config/application.config.php';
unset($configuration['module_listener_options']['config_glob_paths']);
unset($configuration['module_listener_options']['module_map_cache_enabled']);

$serviceManager = new ServiceManager(new ServiceManagerConfig($configuration));
$serviceManager->setService('ApplicationConfig', $configuration);
$moduleManager = $serviceManager->get('ModuleManager');
$moduleManager->loadModules();

Next, create the TestConfiguration.php.dist file. This allows environment-specific configuration without affecting the code base.

touch TestConfiguration.php.dist

Run them jawns

Now that we’re finished with the setup, you’ll need to create a few tests. Once you have some tests to run, you can execute them using the commands below.

# Run all module tests
phpunit

# Run tests for specific module
phpunit --testsuite anothermodule

How to install Apache HTTP Server service script

Recently, after some software and hardware changes, I was forced to rebuild a CentOS 6.5-based virtual machine.  Because the CentOS repository does not include Apache HTTP Server 2.4, and I’m not a big fan of third-party repositories, I decided to compile httpd from source.  When compiling the HTTP server from source, the system administrator is not provided with any service management script; thus, I began my search.

I found a simple service script in an archived version of an old Red Hat user guide, which made things a little easier.

#!/bin/sh
#
# Startup script for the Apache Web Server
#
# chkconfig: 345 85 15
# description: Apache is a World Wide Web server.  It is used to serve 
#	       HTML files and CGI.
# processname: httpd
# pidfile: /var/run/httpd.pid
# config: /etc/httpd/conf/httpd.conf

# Source function library.
. /etc/rc.d/init.d/functions

# See how we were called.
case "$1" in
start)
echo -n "Starting httpd: "
daemon httpd -DSSL
echo
touch /var/lock/subsys/httpd
;;
stop)
echo -n "Shutting down httpd: "
killproc httpd
echo
rm -f /var/lock/subsys/httpd
rm -f /var/run/httpd.pid
;;
status)
status httpd
;;
restart)
$0 stop
$0 start
;;
reload)
echo -n "Reloading httpd: "
killproc httpd -HUP
echo
;;
*)
echo "Usage: $0 {start|stop|restart|reload|status}"
exit 1
esac

exit 0

To create the service script file, follow these directions:

# Create httpd script
touch /etc/init.d/httpd

# Upload, or copy and paste the script contents
nano /etc/init.d/httpd

# Set desired permissions
chmod 0755 /etc/init.d/httpd

# Start httpd on boot, if desired
chkconfig --add httpd
chkconfig httpd on

Upon careful review, you’ll notice the service script assumes that the httpd binary is globally accessible.  Under my minimal CentOS installation, httpd was installed in /usr/local/apache2. While there are more than a few methods for accomplishing this goal, we’ll use a symbolic link.

# Create symbolic link to apachectl
ln -s /usr/local/apache2/bin/apachectl /usr/sbin/httpd

After that, I executed the script which caused a “bad interpreter” error.

[root@localhost]# /etc/init.d/httpd
-bash: ./httpd: /bin/sh^M: bad interpreter: No such file or directory

This error occurs when a file contains CRLF-style line endings (Windows) instead of the LF-style line endings required by Unix-based systems. Luckily, someone invented a utility that fixes this problem quickly and painlessly.

# Install dos2unix
yum install dos2unix

# Fix "bad interpreter" error
dos2unix /etc/init.d/httpd

After that, I could start, stop, and restart the httpd server without any problems. On the other hand, when I tried to retrieve the status directly from the httpd binary (apachectl), I encountered another problem. Luckily, this problem was also easily solvable.

httpd status
# Output: /usr/sbin/httpd: line 95: lynx: command not found

# Install Lynx browser
yum install lynx

And… that’s it!

TPC! Memory Usage 0.9.1 released

After receiving countless emails from supportive users (some nice, some not so nice!), I put the TPC! Memory Usage project back on my ticker.  Despite the vast number of updates to WordPress since December 2010, the Memory Usage plugin has retained the top spot in its niche.  To this day, TPC! Memory Usage is used regularly with only one noticeable problem—a missing bar graph background in the dashboard widget.  As of release 0.9.1, the background has been fixed, and the compatibility data updated for WordPress 3.8.

So… what’s in store for the future?  First, I need to refactor the code to take care of a few notices outputted in debug mode.  In addition, some of the Zend Framework dependencies may be updated, or even eliminated.  Lastly, I’ll put my ear back to the community.  In other words, tell me what you want, and we’ll see what we can do to reach that goal!

Download TPC! Memory Usage 0.9.1 for WordPress

ZF1-ZF2 bridge project available on GitHub

The ZF1-ZF2 Bridge project, based on last week’s post on migrating Doctrine 2 from Zend Framework 1 to Zend Framework 2, has been posted to GitHub. The bridge project accomplishes the following goals, all of which are aimed at easing migration pains.

  • Created ZF1 controller action helper to access ZendMvcApplication
  • Created ZF1 view helper to access ZendViewHelper classes
  • Allow ZF1 controller actions to be routed to ZendMvcApplication without having to edit an .htaccess file
  • Access any ZF2 component from within ZF1 (e.g. ServiceManager, EventManager, MvcEvent, etc.)
  • Full Composer integration for both versions of Zend Framework

Download the ZF1-ZF2 Bridge project from GitHub

Issues with jQuery and ZendFormElementCheckbox

In addition to the more obvious backwards compatibility breaks encountered when migrating from ZF1 to ZF2, there are also more nuanced changes.  In this particular instance, the migration to ZendForm broke the standard code used to determine whether a checkbox input is checked.  The resultant value was always false.

The code we used to determine the a checkbox’s state was extremely simple.

var value = $('input[name="my_element"]').prop('checked') ? 1 : 0;

Next, the ZendForm code responsible for instantiating the element object:

namespace ApplicationForm;

class MyCheckboxForm extends Form
{
    public function __construct($name = null)
    {
        $this->add(array(
            'name' => 'my_checkbox',
            'type' => 'Checkbox',
            'options' => array(
                'label' => 'My Checkbox',
            ),
        ));
    }
}

Under ZendForm, the standard resultant HTML for the checkbox element looks like this:

<input name="my_checkbox" value="0" type="hidden">
<input name="my_checkbox" value="1" type="checkbox">

Gasp… a hidden element! The first input element, which is most certainly not a checkbox, receives priority using the aforementioned selector query. There are a few simple ways to fix this…

Fix #1

It seems as though the creators of Zend Framework had some foresight, and gave programmers the option to disable the hidden element.

$this->add(array(
    'name' => 'my_checkbox',
    'type' => 'Checkbox',
    'options' => array(
        'label' => 'My Checkbox',
        'use_hidden_element' => false,
    ),
));

Fix #2: With Hidden Element

If you wish to retrain the hidden element, you can update the selector query as follows.

var value = $('input[name="my_element"]:checkbox').prop('checked') ? 1 : 0;

Migrating to ZF2: Integrating Composer and DoctrineORMModule

Due to the vast nuances of Zend Framework 2, migrating an application from Zend Framework 1 can be very tedious.  To make this process a little less painful, there is a way to slowly implement modules from ZF2 without making the application unusable. The methodology illustrated, which implements DoctrineModule and DoctrineORMModule into a Zend Framework 1 project, can be applied to a variety of ZF2 modules, making it an invaluable technique in the migration process.

Create the ZF2 project structure

  • /config
  • /config/autoload
  • /data
  • /module
  • /module/Application
  • /module/Application/src
  • /module/Application/src/Application
  • /public
  • /vendor

Install Zend Framework 2 and Doctrine ORM using Composer

At the very least, the composer.json file must include the following.

{
    "require" : {
        "zendframework/zendframework" : "2.2.*",
        "doctrine/orm" : "2.*",
        "doctrine/doctrine-orm-module": "0.*"
    }
}

After updating the Composer configuration file, run Composer.

# Update Composer to latest version
php composer.phar self-update

# Install Composer packages
php composer.phar install

Add init_autoloader.php to application root directory

Integrating the Composer and ZF2 autoloading scheme can be a bit tricky if you rely on antiquated Zend Framework 1 components. To get around the peculiarities, use the classmap generator provided by Zend.

The init_autoloader.php file listed below is identical to the file provided in the ZendSkeletonApplication repository with a few exceptions. For one, the ZF2 autoloader is specified and configured making it simpler to use and understand. Secondly, several class maps are implemented as part of the default autoloading scheme. I recommend generating separate class map files for the application, library (if used), and ZF2 module directories. The class map file in the ZF2 module directory will be replaced with module-specific autoloading once the migration is complete.

// Composer autoloading
if (file_exists('vendor/autoload.php')) {
    $loader = include 'vendor/autoload.php';
}

ZendLoaderAutoloaderFactory::factory(array(
    'ZendLoaderStandardAutoloader' => array(
        'autoregister_zf' => true,
    ),
    'ZendLoaderClassMapAutoloader' => array(
        __DIR__ . '/application/autoload_classmap.php',
        __DIR__ . '/module/autoload_classmap.php',
    ),
));

if (!class_exists('ZendLoaderAutoloaderFactory')) {
    throw new RuntimeException('Unable to load ZF2. Run `php composer.phar install` or define a ZF2_PATH environment variable.');
}

Update ZF1′s index.php for Composer compatibility

There are two changes that will help bring your index file more in line with that of Zend Framework 2.

Place this line at the top of index.php.

NOTE: If relative paths are used in other parts of the application, it is likely that they will need to be updated.

// All paths relative to application root
chdir(dirname(__DIR__));

// Decline static file requests back to the PHP built-in webserver
if (php_sapi_name() === 'cli-server' && is_file(__DIR__ . parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH))) {
    return false;
}

// Setup autoloading
require 'init_autoloader.php';

Setup ZF2 configuration files

In /config, create an application.config.php file using this file as the base. Update the modules entry as listed below.

return array(
    'modules' => array(
        'Application',
        // Vendor modules
        'DoctrineModule',
        'DoctrineORMModule',
    ),
);

Next, create local.php in the /config/autoload directory using the code below. The database credentials should be updated to match your environment.

<?php

return array(
    'doctrine' => array(
        'connection' => array(
            'orm_default' => array(
                'driverClass' => 'DoctrineDBALDriverPDOMySqlDriver',
                'params' => array(
                    'host'     => 'localhost',
                    'port'     => 3306,
                    'user'     => 'mysqlUser',
                    'password' => 'mysqlPassword',
                    'dbname'   => 'mysql_db',
                ),
            ),
        ),
        'configuration' => array(
            'orm_default' => array(
                // Generate proxies should be FALSE on production servers
                'generate_proxies' => true,
            ),
        ),
    ),
);

Setup ZF2 “Application” module

ZF2′s per-module configuration files make it extremely easy to more effectively organize your entities and repositories. In /module/Application/config, create a file named module.config.php using the code below.

<?php

return array(
    'doctrine' => array(
        'driver' => array(
            'application_driver' => array(
                'class' => 'DoctrineORMMappingDriverAnnotationDriver',
                'cache' => 'array',
                'paths' => array(
                    dirname(__DIR__) . '/src/Application/Entity',
                ),
            ),
            'orm_default' => array(
                'drivers' => array(
                    'ApplicationEntity' => 'application_driver',
                ),
            ),
        ),
    ),
);

Next, create Module.php in /module/Application. This file will become more important once the migration is complete.

<?php

namespace Application;

use ZendModuleManagerFeatureConfigProviderInterface;
use ZendModuleManagerFeatureAutoloaderProviderInterface;

class Module implements ConfigProviderInterface,
    AutoloaderProviderInterface
{
    public function getConfig()
    {
        return include __DIR__ . '/config/module.config.php';
    }

    public function getAutoloaderConfig()
    {
        return array(
            'ZendLoaderStandardAutoloader' => array(
                __NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__,
            ),
        );
    }
}

Relocate existing entities and repositories to ZF2

Assuming your entities and repositories share a common namespace, create two new directories inside /module/Application/src/Application. The first directory should be entitled Entity, and the second, Repository. Next, we will need to move existing entities into the Application module and adjust any references to said entities accordingly.

For example, if you were using Model_Entity or ModelEntity as the prefix or namespace, it will need to be updated to ApplicationEntity. The same applies to repositories; if the prefix or namespace was Model_Repository or ModelRepository, it will become ApplicationRepository.

In summation, our data structures will follow this scheme:

Type Class Name Location
Entities ApplicationEntityEntityName /module/Application/src/Application/Entity
Repository ApplicationRepositoryEntityName /module/Application/src/Application/Repository

Make ZendMvcApplication available in ZF1

Add the following method to Bootstrap.php.

class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
    protected function _initZf2()
    {
        $application = ZendMvcApplication::init(include 'config/application.config.php');

        Zend_Registry::set('zf2', $application);
        return $application;
    }
}

How to use ZF2′s DoctrineORMModule in ZF1

Merely creating the ZendMvcApplication object will ensure that Doctrine is properly setup based on the local.php configuration file. From here, using Doctrine is quite simple. By storing the ZendMvcApplication object in the much maligned Zend_Registry, it is universally accessible via Zend_Registry::get('zf2'). The ZF2 application object can also be accessed using $bootstrap->getResource('zf2').

The following code illustrates how to access Doctrine’s EntityManager, and retrieve an entity and repository.

/* @var $application ZendMvcApplication */
$application = Zend_Registry::get('zf2');
$sm = $application->getServiceManager();
$entityManager = $sm->get('DoctrineORMEntityManager');

// Get repository for EntityName
$repository = $entityManager->getRepository('ApplicationEntityEntityName');

// Find EntityName with ID #7
/* @var $entity ApplicationEntityEntityName */
$entity = $repository->find(7);

Conclusion

This “proxy-like” technique can be applied to many different ZF2 modules, making migration significantly less painful. If I left anything out, please let me know. Also, if you have a better way or other ideas on making migration easier, please feel free to post them.

Using SSH instead of FTP for WordPress updates

Under certain server configurations and conditions, WordPress may require an FTP connection to retrieve and process core, plugin, and theme updates.  If you only see an option for FTP on this screen, do not despair.  You are not alone!  If a server is without the libssl2 library and PECL’s ssh2 package, the SSH2 option will not be listed.  While there are WordPress plugins that mimic this capability using various PHP libraries, implementations at the server level often provide better security and performance.

  1. Download libssh2 (C library implementing SSH2 protocol)
  2. At the command line, type the following
    # Unzip the libssh2 archive
    tar -xf libssh2-1.4.3.tar.gz
    
    # Change directory to libssh2 source
    cd libssh2-1.4.3
    
    # Compile libssh2
    ./configure
    make && make install
    
    # Install ssh2 PECL library
    pecl install ssh2-beta
    

After that, the SSH2 option should appear on the WordPress update screen.
WordPress SSH updates

How to get client IP with PHP behind AWS Elastic Load Balancer

If a PHP application server is located behind Amazon Web Service’s Elastic Load Balancer, or another type of proxy server, it is likely that the traditional mechanism for retrieving the end user’s IP address will not work as expected.  As the request passes through the server, the REMOTE_ADDR key of the $_SERVER variable changes to that of the load balancer; however, all is not lost.  In particular, using the AWS Elastic Load Balancer results in the client IP being transferred to another key in the $_SERVER variable—HTTP_X_FORWARDED_FOR.

The code to find the correct IP address is quite simple:

if (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && $_SERVER['HTTP_X_FORWARDED_FOR']) {
    $clientIpAddress = $_SERVER['HTTP_X_FORWARDED_FOR'];
} else {
    $clientIpAddress = $_SERVER['REMOTE_ADDR'];
}

Keep in mind, we have made no considerations for IP spoofing. As always, ensure you protect yourself with a variety of security techniques.

Preparing an SSL certificate for use with AWS Elastic Load Balancer

Today I was tasked with re-keying our SSL certificate in preparation for the implementation of Amazon Web Service’s Elastic Load Balancer service.  In order to properly implement the load balancer into our existing architecture, it must be able to handle SSL connections.  We current employ GoDaddy’s Premium SSL Certificate, which gives you the familiar green bar in the address bar of your browser.  After copying and pasting the private key, certificate, and certificate chain data into the provided inputs, Amazon returned the following message: “Invalid private key.”

When I generate SSL certificate signing requests, I generally use the following command:

openssl req -new -newkey rsa:2048 -nodes -keyout yourdomain.key -out yourdomain.csr

Unfortunately, the resultant format is not compatible with AWS’s Elastic Load Balancer.  In order to counter the “Invalid private key” error, I issued the following commands:

openssl genrsa -des3 -out yourdomain.key 2048
openssl req -new -key yourdomain.key -out yourdomain.csr

After that, copy and paste the CSR contents into the CSR input provided by GoDaddy.  After doing this, I attempted to restart Apache HTTP Server, and noticed the following errors in /etc/httpd/logs/error_log.

[Mon Oct 07 17:55:24.779930 2013] [ssl:emerg] [pid 23786] AH02204: Init: Pass phrase incorrect for key of yourdomain:443
[Mon Oct 07 17:55:24.779981 2013] [ssl:emerg] [pid 23786] SSL Library Error: error:0D0680A8:asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag

[Mon Oct 07 17:55:24.780076 2013] [ssl:emerg] [pid 23786] SSL Library Error: error:0D0680A8:asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag
[Mon Oct 07 17:55:24.780093 2013] [ssl:emerg] [pid 23786] SSL Library Error: error:0D07803A:asn1 encoding routines:ASN1_ITEM_EX_D2I:nested asn1 error (Type=PKCS8_PRIV_KEY_INFO)

Unfortunately, the new private key required a passphrase and Apache didn’t like that. While there are a number of approaches to resolve the issue between Apache and private key passphrases, I chose to remove it, both for the sake of simplicity, and because the Elastic Load Balancer will not accept a private key containing a passphrase. To remove the passphrase, use the following command:

openssl rsa -in yourdomain.key -out yourdomain.key.nopass

At this point, the HTTP server can be restarted, and the SSL certificate’s private key will work with Amazon Web Service’s Elastic Load Balancer.