Wednesday, August 17, 2011

TIP: Retrieving bootrstap instance/Zend_Application using the front controller Zend Framework


$front = Zend_Controller_Front::getInstance();
$bootstrap = $front->getParam('bootstrap');
$resource = $bootstrap->getResource('viewSettings');

Wednesday, July 20, 2011

TIP: Importing your Project through SVN+SSH using a different port

1.) Edit your subversion config file
shell> sudo vim /etc/subversion/config

2.) Under "tunnels" add this
[tunnels]
ssh23 = ssh -p 23

3.) Now you can use it like this:
shell> svn import myproject svn+ssh23://username@192.100.100.100/usr/local/svn/test -m "initial import of files"

Tuesday, July 12, 2011

Setting up PHPUnit in Zend Framework

I haven't really done much unit testing but recently I have to mingle with it a little bit for this task that I was asked to do. I will walk through on how I set it up in ZF (Zend Framework) and share how I solve some problems I encountered.

I will assume you have already installed PHPUnit. If not go here to read the install documentation.

As you may noticed every time you create a new controller in ZF using zend tool a separate test controller is created in /tests/application/controllers but before we can use PHPUnit we need to setup our bootstrap.

1.) Go to and edit /tests/phpunit.xml and add this:
<phpunit bootstrap="./application/bootstrap.php" colors="true">
    <testsuite name="school">
       <directory>./</directory>
    </testsuite>
  
    <filter>
        <whitelist>
            <directory suffix=".php">../library/</directory>
            <directory suffix=".php">../application/</directory>
            <exclude>
                <directory suffix=".phtml">../application/</directory>
            </exclude>
        </whitelist>
    </filter>
</phpunit>

The above will tell PHPUnit where to find your bootstrap and what type of files to look for. You can use this if you are running test from the test parent directory.

2.) Now edit the /tests/application/bootstrap.php file and add this:
<?php
// Define path to application directory
defined('APPLICATION_PATH')
    || define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../../application'));

// Define application environment
defined('APPLICATION_ENV')
    || define('APPLICATION_ENV', (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV') : 'testing'));

// Ensure library/ is on include_path
set_include_path(implode(PATH_SEPARATOR, array(
    realpath(APPLICATION_PATH . '/../library'),
    get_include_path(),
)));

require_once 'ControllerTestCase.php';

The part you want to take a note on the above script is:
set_include_path(implode(PATH_SEPARATOR, array(
    realpath(APPLICATION_PATH . '/../library'),
    get_include_path(),
)));

This is important because if you do not include the ZF library in your PHP's include path, PHPUnit will not be able to find your library without you explicitly specifying the location.

2.) Now let's create an abstract class for our test cases to extend from. Go to /tests/application and create a file called ControllerTestCase.php and add:
<?php
require_once 'Zend/Application.php';
require_once 'Zend/Test/PHPUnit/ControllerTestCase.php';

abstract class ControllerTestCase extends Zend_Test_PHPUnit_ControllerTestCase
{
    public function setUp()
    {
        $this->bootstrap = new Zend_Application(
            APPLICATION_ENV,
            APPLICATION_PATH . '/configs/application.ini'
        );
        parent::setUp();
    }

    public function tearDown()
    {
        $this->resetRequest()->resetResponse();
        $this->request->setPost(array());
        $this->request->setQuery(array());
    }
}

NOTE: The above class is the class that you will need to extend when writing the actual tests.

3.) Edit your main application bootstrap and add the following:
/application/bootstrap.php

    protected function _initLogger()
    {
        $this->bootstrap('frontController');
       
        if ($this->getEnvironment() == "testing") {
            $writer = new Zend_Log_Writer_Stream(APPLICATION_PATH . "/../data/logs/app.log");
            $filter = new Zend_Log_Filter_Priority(Zend_Log::CRIT);
        }
       
        // register the Zend_Application_Resource_Log plugin first if you havent done so
        $this->registerPluginResource('log', array('writer' => $writer));
       
        // make sure to bootstrap
        $this->bootstrap('log');
       
        // retrieve Zend_Log and add the filter
        $this->_logger = $this->getResource('log')
                              ->addFilter($filter);
    }

Then edit your ErrorController.php and change/append the part in your error action where it says "// Log exception, if logger available" and change it to the following. This is if you happen to be using the default Error Controller:
        // Log exception, if logger available
        $log = $this->getLog();
        if ($log) {
            $message = $this->view->message . PHP_EOL;
            $message .= $errors->exception . PHP_EOL;
            $message .= '---------------------------';
            $log->crit($message);
        }

The above script will attempt to log error messages in the stream location that you set. This is so that if there is an error within your application itself unrelated to the test error such as "Application Error" or "Page Not Found Error", you will be able to debug the test. I realize that I need to do this because PHPUnit does not really report any information when you get these types of error. One example is if you $this->dispatch('/notexist') to a non existing action you will get an error in PHPUnit saying:

Failed asserting last action used <"error"> was "notexist";

That error in PHPUnit will not say much to you to debug from but it will log something in app.log.

4.) Now we can write a sample test script. Edit /tests/application/controller/IndexControllerTest.php if you have one and replace it to:

<?php

file_exists('../bootstrap.php') ? require_once '../bootstrap.php' : '';
require_once 'PHPUnit/Framework/TestCase.php';

class IndexControllerTest extends ControllerTestCase
{
    public function testShouldCallStudentSearch()
    {
        $this->dispatch('/');
        $this->assertAction('index');
        $this->assertController('index');
        $this->assertModule('MyModule');
    }
}

One last thing to note here is the line: file_exists('../bootstrap.php') ? require_once '../bootstrap.php' : ''; that I manually added. I did this so I can test the IndexController.php directly within the controller directory:
shell> cd test/application/controllers
shell> phpunit IndexControllerTest.php

Also notice that our class extends ControllerTestCase instead.

If you want to test every test controller that you created, make sure to test from the test directory:

shell> cd /test
shell> phpunit

Saturday, July 9, 2011

Notes: Zend Framework - Invalid Controller Specified Error in Controller Prefix

If you created a new module manually without zend tool make sure to add:
resources.frontController.params.prefixDefaultModule = "1"

Or the prefix in your controllers under your new module will not work! you'll get errors such as:
Fatal error: Uncaught exception 'Zend_Controller_Dispatcher_Exception' with message 'Invalid controller specified (error)'

This is all because of the prefix... (and also the error controller/view not present)

shell> zf create module newmodulename
shell> zf create controller index 1 newmodulename

This will create something like:

/modules/newmodulename/controllers
indexController.php
class Newmodulename_IndexController extends Zend_Controller_Action
{
}

The highlighted prefix that you will see above is the reason the controllers will generate an error. Now to fix it just add like what I noted earlier:
resources.frontController.params.prefixDefaultModule = "1"

Another fix is you can also edit your bootstrap instead. Just add this:
Bootstrap.php
$this->bootstrap('frontController');
$front = $this->getResource('frontController');
$front->setParam('prefixDefaultModule', 1);

Friday, July 1, 2011

Installing Apache 2.2.19 with SSL from source in Ubuntu

Before installing Apache 2, we need to install OpenSSL.

1.) Download OpenSSL from http://www.openssl.org/source/openssl-1.0.0d.tar.gz:
shell> wget http://www.openssl.org/source/openssl-1.0.0d.tar.gz

2.) You want to at least verify the md5 checksum of the openssl tar source and compare the md5 hash string with the one provided in the Apache web site (for this version: http://www.openssl.org/source/openssl-1.0.0d.tar.gz.md5) OR better yet use GnuPG:
shell> md5sum openssl-1.0.0d.tar.gz
shell> 40b6ea380cc8a5bf9734c2f8bf7e701e  openssl-1.0.0d.tar.gz ;: now compare the md5

3.) If everything is well, untar and install:
shell> tar xzvf openssl-1.0.0d.tar.gz
shell> cd openssl-1.0.0d
shell> ./config --prefix=/usr/local/lib/openssl -fPIC

NOTES: I have to use -fPIC for some reason or the configure will keep generating an error but try first without it.

4.) Make a soft link of the bin/openssl
shell> sudo ln -s /usr/local/lib/openssl/bin/openssl /usr/local/bin/

Now we need to create a private key and a certificate.
5.) Lets create our server's private key:
shell> openssl genrsa -des3 -out server.key 1024

6.) Now lets create a Certificate Signing Request (CSR) and sign it using our private key (server.key):
shell> openssl req -new -key server.key -out server.csr

NOTE: You usually send the CSR to a CA or Certificate Authority such as Verisign (Im clueless, never done it) but for now we cannot wait and we want to test! We can act as our OWN Certificate Authority and sign our CSR. This will not be valid for browsers and will tell you the Certificate is not from a valid authority.

7.) Lets use our server's private key (server.key) to sign our Certificate Signing Request (CSR) or you can create another private key acting as a Certificate Authority (CA). From there we can sign and create our own CRT (Certificate):
shell> openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

Now we have a Private key (server.key) and a signed certificate (server.crt)

8.) Lets add this public key and certificate to a location we can remember:
shell> mv server.key /usr/local/ssl/privatekeys/
shell> mv server.crt /usr/local/ssl/certificates/

We can start installing Apache 2.

9.) Download Apache 2.
shell> wget http://www.takeyellow.com/apachemirror//httpd/httpd-2.2.19.tar.gz
shell> tar xzvf httpd-2.2.19.tar.gz

10.) Before installing, lets compare the md5 checksum of our package to the ones from Apache.org so we can have a little peace of mind that the integrity of the source files has not been compromised:
shell> md5sum httpd-2.2.19.tar.gz
shell> e9f5453e1e4d7aeb0e7ec7184c6784b5 httpd-2.2.19.tar.gz
 *Compare that md5 with this: http://www.apache.org/dist/httpd/httpd-2.2.19.tar.gz.md5

If everything seems to look right, lets proceed with the installation

11.)  Install Apache 2 and enable SSL support:
shell> cd httpd-2.2.19
shell>sudo ./configure --prefix=/usr/local/lib/apache2 --enable-mods-shared=most --enable-ssl --with-ssl=/usr/local/lib/openssl
shell> sudo make
shell> sudo make install

12.) If everything went smooth, lets add our private key and certificate to Apache:
shell> sudo vim /usr/local/lib/apache2/conf/extra/httpd-ssl.conf

13.) Look for the line SSLCertificateFile "/usr/local/ssl/server.crt" and SSLCertificateKeyFile "/usr/local/ssl/server.key" and replace it with your proper certificate and key location

Mine will be:
SSLCertificateFile "/usr/local/ssl/certificates/server.crt"
SSLCertificateKeyFile "/usr/local/ssl/privatekey/server.key"

14.) Go to your Apache's httpd.conf and uncomment the include for httpd-ssl.conf
shell> sudo vim /usr/local/lib/apache2/conf/httpd.conf

15.) Make a soft link of apachectl then start Apache:
shell> sudo ln -s /usr/local/lib/apache2/bin/apachectl /usr/local/bin/
shell> sudo apachectl start

IMPORTANT: The above steps are just fast walk through and did not consider any security concerns in setting up Apache. Please research further on how to secure your web server efficiently.

Thursday, June 30, 2011

Installing Subversion from source and mod_dav_svn in Apache

Installing Subversion from  source was one of the most frustrating thing I have done because of its dependencies so I'll summarize here a short process to do it.

1.) Download and extract Subversion from here http://subversion.apache.org/download:
shell> cd /usr/local/src
shell> wget http://subversion.tigris.org/downloads/subversion-1.6.17.tar.gz
shell> sudo tar xzvf subversion-1.6.17.tar.gz

2.) Install the dependicies and development packages (they need to be the development '-dev'). Below are the libs that it took me awhile to find:
shell> sudo apt-get install libxml-dev
shell> sudo apt-get install libssl-dev
shell> sudo apt-get install zlib1g-dev

3.) Install Subversion. I will assume that you already installed Apache, mod_ssl and signed your certificates if not refer to this other blog post of mine in installing apache:
shell> cd /usr/local/src/subversion-1.6.17.tar.gz
shell> sudo ./configure --prefix=/usr/local/lib/subversion --with-apxs=/usr/local/apache2/bin/apxs --with-ssl

NOTES: Some installation that I read from other websites suggests you to include neon, apr, apr-utils like this for example:
shell> sudo ./configure --prefix=/usr/local/lib/subversion --with-apxs=/usr/local/apache2/bin/apxs --with-apr=PATH-TO-APR --with-apr-util=PATH-TO-UTIL --with-neon=PATH-TO-NEON --with-openssl=PATH-TO-OPENSSSL --with-ssl

You dont have to do the above! Infact when I did that build, that's when my headache started because of the dependencies. You also do not need to install the individual packages that are required namely apr, apr-utils, and neon. The install script will automatically search for the libraries included with the tar package you downloaded.

Then after configure finishes:
shell> sudo make
shell> sudo make install

This will install the mod_dav_svn.so and mod_authz_svn.so in the modules directory of your Apache installation.

EXTRAS: Some stuffs that I discovered along the way (just sharing :P ):

- This will return the list of files that are using this library that you installed through apt-get. In other words, the installed file locations:
shell> sudo dpkg -L libssl-dev

- Will look at your apt-get history and return which packages you have installed in the past
shell> grep -nwH install /var/log/dpkg.log ;: look at installs
shell> grep -nwH removes /var/log/dpkg.log ;: look at removes

- Download the source from the package distribution then install it yourself from source instead.
shell> sudo apt-get source libapache2-svn ;: will download and extract the source files
shell> sudo apt-get build-dep libapache2-svn ;: this will install all the dependencies
shell> cd subversion-1.6.12dfsg
shell> sudo ./configure --prefix=PATH --with-apxs=PATH-TO-APXS-FILE

Thats it!

Thursday, June 23, 2011

Notes on Setting up Subversion in Ubuntu

Quick walkthrough on setting up subversion in your own server. I will use WebDAV in order to communicate with Apache and quick setup of Samba in case you want to look at your repository in Windows.

1.) Install subversion
shell> sudo apt-get install subversion

2.) Add a subversion group:
shell> sudo groupadd subversion

3.)  Add your username and www-data to the group subversion:
shell> sudo gpasswd -a username subversion
shell> sudo gpasswd -a www-data subversion

4.) Create your repository. I chose mine to be created in /usr/local
shell> cd /usr/local
shell> mkdir svn/myproject ;: this is the name of my repository
shell> chown -R www-data:subversion svn/myproject
shell> chmod -R g+rws svn/myproject
shell> cd svn
shell> svnadmin create myproject ;: for organizational purposes, svn dir will hold different projects

5.) Import our project. I choose to create a trunk here.
The project here is empty or nonexisting yet. Also, you need to go out outside the /usr/local/svn directory
shell> cd /home/projects
shell> mkdir -p myproject/trunk
shell> svn import myproject file:///usr/local/svn/myproject -m "Initial import"

This will create project "myproject" in /svn/myproject thus creating you a directory structure in svn repo like /svn/myproject/trunk

5b.) If you need to import an existing project with existing files inside it do:
shell> cd /home/superman/www/myproject ;: assume this is my project location
shell> svn import . file:///usr/local/svn/myproject/trunk -m "Initial import of project Superproject"

Notice that I created a trunk directory via import command

6.) Lets install the WebDAV SVN module in apache.
shell> sudo apt-get  libapache2-svn
shell> sudo vim /etc/apache2/mods-available/dav_svn.conf

7.) Add this:
  <Location /svn/myproject>
     DAV svn
     SVNPath /usr/local/svn/myproject
     AuthType Basic
     AuthName "SVN Repo"
     AuthUserFile /etc/subversion/passwd
     <LimitExcept GET PROPFIND OPTIONS REPORT>
        Require valid-user
     </LimitExcept>
  </Location>

8.) Now lets create the passwd file
shell> sudo htpasswd -c /etc/subversion/passwd username ;: -c to create the file
shell> sudo htpasswd /etc/subversion/passwd batman ;: add another user. no -c this time
shell> sudo apache2ctl restart

9.) NOTES: If you happen to have permissions problem like if you are using tortoise and trying to commit but wont let you do it do:
shell> sudo gpassswd -a www-data subversion :; make apache part of the group
shell> cd /usr/local/svn/myproject :; make sure myproject is owned by www-data
shell> sudo chown -R www-data:subversion . :; we did this earlier but just making sure

10.) OPTIONAL. If you have samba installed and want to add /usr/local/svn
shell>sudo vim /etc/samba/smb.conf
Then add this:
[svn]
   path = /usr/local/svn
   writeable = yes
   browseable = yes
   valid users = username
   guest ok = no

11.) Checking out your project
shell> cd /home/superman/projects/www
shell> mkdir myproject
shell> svn checkout file:///usr/local/svn/myproject/trunk myproject

12.) When checking out in Windows using Tortoise SVN use:
http://[ip of svn server]/svn/myproject/trunk 

The above link is the one to use also for viewing your SVN tree structure via a web browser and will only work if you install the WebDAV module in Apache.