Screenshot

Events Reference for ZF2 Applications

One of the most powerful aspects of a Zend Framework 2 application is the event manager. Right out of the box a skeleton application has impressive features which can be added to or replaced using events. Events also make it possible to write modules that can interact with the application while keeping its own code completely separate.

The downside to events is that they add a layer of abstraction that makes it more difficult to understand and trouble shoot an application. To write new event listeners or trouble shoot existing ones you need to understand how they all work together, but it is difficult to even know what listeners are attached to which events. As your application becomes more complicated it becomes more difficult to keep track of how all the pieces fit together.

To help myself keep track of event listeners in my applications I wrote a view helper that can inspect an Event Manager object and render a list of events and their corresponding listeners. You can see it in action with this live demo of events reference. This alone is helpful to understand the basic structure of a ZF2 application, but to take full advantage of the helper you’ll want to be able to use it in your own application. Lucky for you I added it to the Spork Tools module and you find the source code on GitHub.

To use the view helper all you need to do is pass an event manager object to it as a parameter. Keep in mind this could reveal security sensitive information so you should make sure this is not publicly accessable.

// controller action
public function indexAction()
{
    return array(
        'events' => $this->getApplication()->getEventManager(),
    );
}

// view script
echo $this->sporkToolsEvents($events);

Using HTML52PDF to create text documents in PHP

I’ve been trying out different PHP libraries to generate text documents. My previous post Using PHPWord to generate text documents in PHP describes my quest in more detail.

This time around I’m tying out the HTML52PDF library (http://www.html52pdf.com/). Despite what it’s name suggests the library is not PDF specific and actually supports the Open Document format directly. The library is actively being developed. It’s website is nice looking, has tutorials and documentation. The only downside is that using the library for commercial use requires a license that starts at $199, but if the library provides what the website claims it would be well worth it.

The demo I created to test the library is available here http://sporkcode.com/sandbox/document/html52pdf.

The first problem I ran into with the library is that it generates a strict standards level error when you try to create a document. To get around the problem I disabled error reporting of non fatal errors around the render document function call. After that the document would render, but it’s very surprising that a commercial library would have such a obvious problem in the code.

Open Document Format

The Open Document file rendered pretty well except it striped out text that was not wrapped in an HTML tag. This is a problem because that is how most of the text is returned by the Dojo HTML Editor (using Firefox). It is interesting that the PHPWord library had a similar problem.

Open Document Text file generated by HTML52PDF screen capture

screen capture of Open Document Text file generated by HTML52PDF

Portable Document Format (pdf) & Office Open XML (docx)

To generate PDF, Office Open XML or RTF documents the library requires LibreOffice to be installed on the server and setup to use an extension included in the HTML52PDF library and then to run an additional PHP script as a service which translates the Open Document file into another format with LibreOffice. I set this up on my development server, but my first attempt generated additional warnings and errors when I tried to generate formats other than Open Document. After changing where I was saving the files from the system temporary folder to a folder with different permissions and tweaking the service script. I was able to generate other formats. I decided against going through the same process on my production server so the demo does not production Office Open XML (docx) or PDF files.

Conclusion

It’s really hard to feel confident in a library that generates warnings using its most basic functions. Even though the warnings don’t prevent the library from functioning it makes me question how much testing went into its release and spending $199 on licensing software that has such obvious defects.

The dependency on LibreOffice libraries to generate formats other that Open Document seems problematic as it means extra setup on a production server and may introduce compatibility issues with later versions of LibreOffice. The PHP script that you have to run as a service gave me additional concerns. First the library doesn’t provide any tools to launch the script which means additional server setup and maintenance. It also means that if the script crashes, rendering formats other than Open Document will stop working without any warning, unless you setup some kind of monitoring solution to check that the script is runing. Finally the libraries installation guide recommends running the script as root which is an obvious security vulnerability. If I did go ahead with using this software I think I would only use it to generate Open Document files, but that seriously reduces it usefulness.

In the end the library does to a good job rendering Open Document Text files, but there are several issues that make it difficult for me justify the $199 it costs to license it.

 

Using PHPWord to generate text documents in PHP

I started working on a project where I need to generate reports as text documents that can then be edited with a word processor. The reports will be a combination of rich text blocks from HTML and data sets in tables. Open Document (odt) or Microsoft’s Office Open XML (docx) are both suitable choices for the file format since they are both open and supported by most word processors.

It’s relatively easy to generate Open Document spreadsheets, but converting HTML text into a formatted document is much more difficult. Luckily there are a handful PHP libraries out there for working with Open Document or Office Open XML files that could make this project a lot easier. To meet my needs the library must be able to create a document, import HTML blocks and create tables. I’m going to test the most promising looking libraries, compare the results and post my results here. I’ve created a live demo for testing each library which can be found here http://sporkcode.com/sandbox/document.

PHPWord

https://github.com/PHPOffice/PHPWord

Demo http://sporkcode.com/sandbox/document/phpWord

PHPWord looks very promising. It’s open source, actively maintained, has documentation and examples, supports many file formats and has an extensive API for working with documents. It’s also also easy to install using composer.

Unfortunately the library failed to format the document correctly in the demo. The first problem is that it doesn’t recognize <b> or <i> tags in the HTML. This seems like a pretty glaring omission, but it was easy to get around by using HTML Purifier to change the tags into <strong> and <em>. The library also has problems formatting text that has inline HTML tags, but is not wrapped in a block level tag such as a <p>. This especially a problem since text generated by HTML editor in the demo is not always wrapped in block level tags.

Open Document Text

The Open Document text file had many rendering problems.

PHPWord Open Document Text screen capture

Screen capture of Open Document Text file created by PHPWord

As the image above shows the heading tag did not render any formatting, inline tags did not render correctly when not inside another tag (as mentioned above), the unordered and ordered list did not render at all and the table cells did not render any formatting.

Office Open XML

The Office Open XML document rendered better, but still had problems.

PHPWord Office Open XML screen capture

Screen capture of Office Open XML generated by PHPWord

There are still problems with inline tags not wrapped in block level tag. The table styles rendered correctly, but the first columns took up the entire width of the document until I set a static column width.

Portable Document Format (pdf)

The library has the option to render to a PDF, however it requires an additional library which I didn’t test because of the problems with Open Document and Office Open XML formats.

Other Issues

I took a quick look at the source code to see how difficult it would be to fix some of the problems and was not very impressed with what I found. The code seems rather thrown together. There are unnecessary static functions, arguments passed by reference and use of reflection classes. Not that there was anything wrong with the code, but it doesn’t utilize what I would consider best practices. It appears that the project is a branch of a project of the same name created by CodePlex, which could explain the patchwork nature of the code.

Another thing that annoyed me is that all of the syntax for document styling uses older HTML attribute names (valign, bgcolor) instead of using CSS conventions.

Conclusion

Overall the library has impressive features and appears well supported, but sill has plenty of issues. Even though the project is supported I have doubts that it will become stable. I was very disappointed by the results of the Open Document support and if I use this library I will definitely stick with Office Open XML.

Next: Using HTML52PDF to create text documents in PHP

Integrating Stylus, Less or Sass in a Zend Framework 2 application

I’ve been using CSS preprocessor languages for a while. I’ve tried Less, Sass and have adopted Stylus for most of my projects. All three make creating, maintaining and minimizing complicated style sheets easier, but come at the price of having to recompile after every update. Part of the appeal of script languages like PHP, JavaScript, HTML and CSS is that you don’t have to recompile to test changes, which speeds up development. The power of using a CSS preprocessor easily outweighs the inconvenience of compiling the code, but it still left me looking for a better way to integrate them into my workflow.

So I decided to write a PHP wrapper class for CSS preprocessors to integrate them into my Zend Framework 2 applications. This lets me trigger a CSS update in a controller or with a listener that updates the CSS when it is out of date. It also lets me use CSS preprocessors to include CSS inline in view templates, but I’ll go into that in another post. The result is I can edit Less, Sass or Stylus files and the changed CSS immediately shows up in my development environment without having to go back to the command line and all it takes is a minimal amount of configuration in my application.

I included the classes in the Spork ZF2 Library. The source code for the classes is available on GitHub here and there is some documentation in README.md.

Once you have the preprocessor installed and the classes are available in your application all you need to do is configure your application to use the Update Listener, tell it which preprocessor to use, where your source files are and where you want the CSS to go. Here is the basic configuration to use Stylus.

    'css-update' => array(
        'compiler' => 'cssStylus',
        'builds' => array(
            array(
                'source' => 'path/to/source',
                'destination' => 'path/to/destination',
                'includes' => array('path/to/include') // optional
                'compress' => true // optional
            ),
        ),
    ),
    'service_manager' => array(
        'invokables' => array(
            'cssStylus' => 'Spork\CSS\Stylus',
            'cssUpdateListener' => 'Spork\CSS\UpdateListener', 
        ),
    ),
    'listeners' => array(
        'cssUpdateListener',
    ),

A couple notes. I do not recommend using this in a production environment. I use this in my development environment and uploaded the CSS files to my production environment. The destination folder must be writable by the webserver.

XDebug and PDT highlight wrong line in Eclipse

After upgrading to Eclipse 4.4 (Luna) I started having problems debugging PHP files with XDebug. The problem is the code editor would highlight the wrong line when it jumped from one file to the next, but it would move to the correct line after stepping to the next line in the file. I was hoping the problem would be fixed in 4.4.1 (Luna SR1), but the problem got worse and the editor would only highlight the line with the break point and not move at all.

Luckily the bug has been fixed and is available in the PDT night builds, but not as a release yet. To get it add http://download.eclipse.org/tools/pdt/updates/3.3-nightly/ to Eclipse’s available software sites (Preferences -> Install / Update -> Available Software Sites) and install updates (Help -> Check for Updates).

More info here https://www.eclipse.org/forums/index.php/t/823451/

Found missing spell checker in Eclipse for PHP Developers

After a recent upgrade I discovered that spell checking had stopped working in Eclipse. The spelling configuration in preferences only displayed the less than helpful message ‘The spelling service is not installed’. I looked around for a missing Eclipse plug-in or something not installed in Linux but couldn’t find anything helpful. Finally I found a bug report that shed some light on the problem. Turns out the spell checking functionality is bundled with the JDT. When I upgraded I installed the new Eclipse for PHP Developers package which doesn’t include JDT and hence no spell checking. Installing JDT in Eclipse fixed the problem, but a more helpful message in the spelling preferences would have saved me a lot of time.

PHP Inline type hinting in Eclipse

For the most part type hinting works pretty well using PDT in Eclipse. It speeds up coding and the best part is Eclipse will automatically determine variable types from class definitions and DocBlock comments. Eclipse also supports inline type hints for when it cannot determine a variable’s type, but the format is a little different than normal DocBlock comments and I always end up having to search for examples when I need it. So I leaving myself a reminder here and hopefully it will be helpful to someone else as well.

This usually comes up when I’m iterating through a list of objects…

foreach ($arrayOfObjects as $object) {
    $object->property;
    $object->method();
}

It would be nice if Eclipse could help me out with the properties and methods for $object, but it has no way of determining type type of $object. Inline type hinting to the rescue…

/* @var $object \My\Object */
foreach ($arrayOfObjects as $object) {
    $object->property;
    $object->method();
}

Now Eclipse will happily auto complete methods and properties for $object. The part I always forget is that this is not a DocBlock comment (one asterisk /* instead of two /**) and that the variable’s type comes after the variable’s name, which is the opposite of other PHPDoc tags. Eclipse is very particular about this and type hinting will not work if it’s not right. Another important thing to keep in mind is that types in comments must include the complete namespace including the leading slash.

Dojo Theme Demo

Recently I was working on a new design for a project and trying create a Dojo Theme to go along with it. I’ve always had kind of mixed feelings about Dojo Themes. On one hand having a clean, consistent look for all the form and layout elements right out of the gate is awesome and can really speed up initial development. On the other hand customizing parts of a theme, like a lot of things in Dojo, has a very steep learning curve and even making what seem like trivial changes can quickly become a huge headache.

I decided to try to avoid some of the problems I’ve run into before by creating a complete theme instead of just hacking parts of one of the default themes as I went along. Dojo has a theme tester page which is very helpful for just this task. I also decided it would be a good time to to learn Less since the Claro theme uses it. The learning curve for Less is pretty small and after playing with it a little I can’t imagine trying to write style sheets for a site without it.

Then I got the idea to try to use Less to build a more dynamic theme tester that would let you change values in the style sheets similar to the ThemeRoller for jQuery UI. After hacking together a custom version of Less I came up with this proof of concept page http://sporkcode.com/sandbox/dojoThemeShrine. Basically I got Less to save a list of variables and their values as it compiles the styles sheets. The page then creates a text input for each variable and when one is changed it tells Less to recompile the styles sheets with the new values. It’s a little slow, but it works and it nice to see changes without having to edit, save, compile, refresh.

When I have some more time I’m going to making this more functional. I think making mixins editable along with variables would be a good next step. I’m also thinking about coming up with a way to group the variable by namespace or maybe by file. Being able to export the updated style sheet would also be handy. I’m also going to clean up some of the changes I made to Less and include them in a feature request to have an option for the compiler to map variables and mixins.

Disable Layout in Zend Framework 2

It never fails. Every time I start a new ZF2 project I end up needing to disable the layout for certain responses. Usually it’s to feed some HTML content to a Dojo Dialog or something else involving XHR. Being a firm believer in RTFM first I look through the ZF2 Reference Guide which provides no help. Then I dive into the ZF2 source code which also provides no answers. After a bit of cursing my frustration leads me to Google which yields Zend Framework 2 : Disable Layout in specific Module. OK that was more difficult than is should have been, but at least it works… except… the obsessive compulsive part of me just can’t let it go without knowing “Why does it work?”, “Why isn’t there a simpler solution?” So to hopefully save myself, and other obsessive compulsive programmers, from future frustration here is the how and why.

Looking at the source code the MVC seems to create the layout out of some kind of magical programming aether. The magic starts way back during the Application’s bootstrap event when the ViewManager object is created. As part of it’s bootstrap listener the ViewManager initializes the MvcEvent’s ViewModel and sets its template to the configured layout. So how does it get the content into the layout? This happens during the dispatch event in the InjectViewModelListener which sets the ViewModel result returned from the dispatched controller as the child of the ViewModel created by the ViewManager. The trick of disabling the layout works because of 4 very inconspicuous lines in the InjectViewModelListener which replace the default ViewModel (which renders the layout) with the ViewModel returned from the controller action, if it’s terminal flag is true, instead of setting it as a child.

OK lets back up and try something simple to illustrate. We can disable the layout in a controller action by simply returning a ViewModel with the terminal flag set to true.

class MyController extends AbstractActionController
{
    public function myAction()
    {
        $viewModel = new \Zend\View\Model\ViewModel();
        $viewModel->setTerminal(true);
        return $viewModel;
    }
}

Pretty strait forward. When the InjectViewModelListener checks the terminal flag of our ViewModel it will set it as the ViewModel for MvcEvent, which replaces the default ViewModel and disable the layout. So how about disabling the layout for the entire controller?

class MyController extends AbstractActionController
{
    public function myAction()
    {
        $myViewModel = new \Zend\View\Model\ViewModel();
        return $myViewModel;
    }
    protected function attachDefaultListeners()
    {
        parent::attachDefaultListeners();
        $eventManager = $this->getEventManager();
        $eventManager->attach(
            \Zend\Mvc\MvcEvent::EVENT_DISPATCH,
            function(\Zend\Mvc\MvcEvent $event) {
                $myViewModel = $event->getResult();
                if ($myViewModel instanceof \Zend\View\Model\ViewModel) {
                    $myViewModel->setTerminal(true);
                }
            },
            -99);
    }
}

Still pretty strait forward. This time we attach a callback to the dispatch event which sets the terminal flag to true for any ViewModel returned from any action in controller. Notice the priority of -99 which places the listener just before the InjectViewModelListener but after any other listeners which modify the results of the controller’s action. This is especially important if any of the controllers actions return something other than a ViewModel such as an array or null.

So to disable the layout for all XMLHttpRequests for the entire application we should be able to use the same callback with a condition that tests for a XMLHttpRequest in our Module class… right? Well not quite. The problem is that the InjectViewModelListener doesn’t listen for the Application’s dispatch event; it is attached to the Controller’s dispatch event. The fact that the dispatch event triggers another dispatch event makes me want to throw my hands up, call it a day and head to the pub, but I’ll press on a little more. To make it work outside of the controller we need to use the shared event manager and attach it to the dispatch event for any controller.

namespace MyModule;

class Module
{
    public function onBootstrap(\Zend\Mvc\MvcEvent $event)
    {
        $sharedEventManager = $event->getApplication()
            ->getEventManager()->getSharedManager();
        $sharedEventManager->attach(
                'Zend\Mvc\Controller\AbstractController',
                \Zend\Mvc\MvcEvent::EVENT_DISPATCH,
                function(\Zend\Mvc\MvcEvent $event) {
                    $request = $event->getRequest();
                    if ($request->isXMLHttpRequest()) {
                        $dispatchResult = $event->getResult();
                        if ($dispatchResult instanceof ViewModel) {
                            $dispatchResult->setTerminal(true);
                        }
                    }
                },
                -99);
    }
}

This does the same thing, but uses the shared event manager to attach the listener to all controllers. As confusing as having the dispatch event trigger another dispatch event is it is also what allows us to target specific modules or even controllers. In the code above ‘Zend\Mvc\Controller\AbstractController’ could be replaced with a specific module or controller.

To make things a little more portable you could also add the following class to your library.

<?php
namespace MyLib\Mvc\Listener;

use Zend\EventManager\AbstractListenerAggregate;
use Zend\EventManager\EventManagerInterface;
use Zend\Mvc\MvcEvent;
use Zend\View\Model\ViewModel; 

class XMLRequestListener extends AbstractListenerAggregate
{
    public function attach(EventManagerInterface $events)
    {
        $sharedEvents = $events->getSharedManager();
        $this->listeners[] = $sharedEvents->attach(
            'Zend\Mvc\Controller\AbstractController',
            MvcEvent::EVENT_DISPATCH,
            array($this, 'handleXMLRequest'),
            -99);
    }

    public function handleXMLRequest(MvcEvent $event)
    {
        $request = $event->getRequest();
        if ($request->isXMLHttpRequest()) {
            $dispatchResult = $event->getResult();
            if ($dispatchResult instanceof ViewModel) {
                $dispatchResult->setTerminal(true);
            }
        }
    }
}

Then all you would need to do is add the following to your module

public function onBootstrap(MvcEvent $event)
{
    $eventManager = $event->getApplication()->getEventManager();
    $eventManager->attachAggregate(
            new MyLib\Mvc\Listener\XMLRequestListener());
}