• 2015-10-04 13:26:00

    Building the Phalcon Blog (i)

    This is the first of a series of posts, describing how we built the Phalcon Blog (and this one of course). The intention is to showcase some of the features of Phalcon and discuss the reasons behind implementing the code in such a way. I will amend this post with the links of the future posts once I post them.

    These series will focus initially on the Phalcon blog (Github) and will then expand on this blog (Github). In the very near future all the features available in this blog will be available in the Phalcon one :)

    As I mentioned in a previous post, Andres and I were not 100% satisfied with Tumblr, the blogging platform that we have used for a few years for the purposes of the Phalcon blog. So we decided that it would not only be beneficial for us to build something of our own, but also for the community, since the software is open sourced and available for everyone to use.

    Bootstrapping process

    In this post I am going to concentrate on bootstrapping the application. By bootstrapping I do not mean using the Bootstrap open source library, despite the probably misleading image on the right.

    Bootstrapping is the class (in our case) that handles pretty much everything that our application needs to run prior to executing actions. This entails

    • Conditional execution between the normal app and the CLI one
    • Application Paths
    • Configuration Files
    • Loader (and composer autoloader) setup
    • Error handling
    • Routes
    • Dispatcher
    • Url
    • Views
      • Main View
      • Simple View (for emails, RSS/Sitemap etc.)
    • Cache
    • Utils
    • Post Finder class

    Some of the above components are also registered in the DI container for further use in the application.

    Implementation

    In other applications we have open sourced such as Vokuro, we have pretty much always included a couple of files in our index.php; one for the loader and one for the services as demonstrated here.

    <?php
    
    error_reporting(E_ALL);
    
    try {
        /**
         * Define some useful constants
         */
        define('BASE_DIR', dirname(__DIR__));
        define('APP_DIR', BASE_DIR . '/app');
        /**
         * Read the configuration
         */
        $config = include APP_DIR . '/config/config.php';
        /**
         * Read auto-loader
         */
        include APP_DIR . '/config/loader.php';
        /**
         * Read services
         */
        include APP_DIR . '/config/services.php';
        /**
         * Handle the request
         */
        $application = new \Phalcon\Mvc\Application($di);
        echo $application->handle()->getContent();
    } catch (Exception $e) {
        echo $e->getMessage(), '<br>';
        echo nl2br(htmlentities($e->getTraceAsString()));
    }
    

    There is nothing wrong with the above approach. We did however consider the fact that the particular index.php file has 3 different file inclusions and if we wanted to tinker with the setup of the application we would have to open all three.

    We opted for one file containing all of our services and application bootstrap. In addition to that, we altered the design so that later on we can add a CLI application without much effort and heavy refactoring.

    NOTE: The CLI application has been implemented on this blog and will very soon be merged to the Phalcon repository. We will cover that functionality in a future post.

    index.php

    Having one file that performs all the necessary initialization tasks a.k.a. bootstrapping our application allows us to have a much smaller index.php file. (comments removed to preserve space)

    <?php
    
    use \Phalcon\Di\FactoryDefault as PhDI;
    use \Kitsune\Bootstrap;
    
    error_reporting(E_ALL);
    
    try {
        require_once '../library/Kitsune/Bootstrap.php';
    
        $di = new PhDI();
        $bootstrap = new Bootstrap();
    
        echo $bootstrap->run($di, []);
    } catch (\Exception $e) {
        if ($di->has('logger')) {
            $logger = $di->getShared('logger');
            $logger->error($e->getMessage());
            $logger->error('<pre>' . $e->getTraceAsString() . '</pre>');
        }
    }
    

    We create a new bootstrap application and pass in it a DI container. For this part of the application the FactoryDefault DI container is used. However we will be able to inject a Phalcon CLI DI container for the CLI application we will discuss later on.

    Bootstrap.php

    Our bootstrap class contains all the code we need to run the application. It is a bit shy of 400 lines which according to PHP Mess Detector is not something we want to be doing because it increases complexity and if we are not careful it will create a mess :). We opted to ignore that rule and left the file as is because once we had everything working as we wanted, we were not going to be messing with that file again.

    Constants

    We use several constants throughout the application.

    • K_PATH - the top folder path of our installation
    • K_CLI - whether this is a CLI application or not
    • K_DEBUG - whether we are in debug/development mode. In this mode all volt templates are being created at every request and cache is not used.
    • K_TESTS - whether we are running the test suite or not (test suite is not implemented yet)
            /**
             * The app path
             */
            if (!defined('K_PATH')) {
                define('K_PATH', dirname(dirname(dirname(__FILE__))));
            }
    
            ....
    
            /**
             * Check if this is a CLI app or not
             */
            $cli   = $utils->fetch($options, 'cli', false);
            if (!defined('K_CLI')) {
                define('K_CLI', $cli);
            }
    
            $tests = $utils->fetch($options, 'tests', false);
            if (!defined('K_TESTS')) {
                define('K_TESTS', $tests);
            }
    
            ....
    
            /**
             * Check if we are in debug/dev mode
             */
            if (!defined('K_DEBUG')) {
                $debugMode = boolval($utils->fetch($config, 'debugMode', false));
                define('K_DEBUG', $debugMode);
            }
    
    Configuration

    The configuration is split into two files. The git tracked base.php (under /var/config/) contains an array of elements that are needed throughout the application, such as cache settings, routes etc. The config.php located in the same folder is installation dependent and is not tracked in git. You can override every element that exists in base.php.

            /**
             * The configuration is split into two different files. The first one
             * is the base configuration. The second one is machine/installation
             * specific.
             */
            if (!file_exists(K_PATH . '/var/config/base.php')) {
                throw new \Exception('Base configuration files are missing');
            }
    
            if (!file_exists(K_PATH . '/var/config/config.php')) {
                throw new \Exception('Configuration files are missing');
            }
    
            /**
             * Get the config files and merge them
             */
            $base     = require(K_PATH . '/var/config/base.php');
            $specific = require(K_PATH . '/var/config/config.php');
            $combined = array_replace_recursive($base, $specific);
    
            $config = new Config($combined);
            $di->set('config', $config, true);
    
    Loader

    The loader uses the namespaces defined in the base.php and config.php. Additionally the composer autoloader is included to offer functionality needed from the composer components we have.

            /**
             * We're a registering a set of directories taken from the
             * configuration file
             */
            $loader = new Loader();
            $loader->registerNamespaces($config->namespaces->toArray());
            $loader->register();
    
            require K_PATH . '/vendor/autoload.php';
    
    Logger

    The logger is set to create a log file every day (with the date as the prefix).

            /**
             * LOGGER
             *
             * The essential logging service
             */
            $format    = '[%date%][%type%] %message%';
            $name      = K_PATH . '/var/log/' . date('Y-m-d') . '-kitsune.log';
            $logger    = new LoggerFile($name);
            $formatter = new LoggerFormatter($format);
            $logger->setFormatter($formatter);
            $di->set('logger', $logger, true);
    
    Error handler

    We decided to have no errors thrown in the application even if those are E_NOTICE. A simple isset() in most cases is more than enough to ensure that there are no E_NOTICE errors thrown in our log. Any errors thrown in the log files slow our application down, even if the errors are suppressed using the php.ini directives. We also set the timezone to US/Eastern in that file. That particular piece could become configurable and stored in the config.php. Finally we specify a custom error handler, to offer verbosity in errors thrown as well as log metrics when in debug mode.

            /**
             * ERROR HANDLING
             */
            ini_set('display_errors', boolval(K_DEBUG));
    
            error_reporting(E_ALL);
    
            set_error_handler(
                function ($exception) use ($logger) {
                    if ($exception instanceof \Exception) {
                        $logger->error($exception->__toString());
                    } else {
                        $logger->error(json_encode(debug_backtrace()));
                    }
                }
            );
    
            set_exception_handler(
                function (\Exception $exception) use ($logger) {
                    $logger->error($exception->getMessage());
                }
            );
    
            register_shutdown_function(
                function () use ($logger, $memoryUsage, $currentTime) {
                    $memoryUsed = number_format(
                        (memory_get_usage() - $memoryUsage) / 1024,
                        3
                    );
                    $executionTime = number_format(
                        (microtime(true) - $currentTime),
                        4
                    );
                    if (K_DEBUG) {
                        $logger->info(
                            'Shutdown completed [Memory: ' . $memoryUsed . 'Kb] ' .
                            '[Execution: ' . $executionTime .']'
                        );
                    }
                }
            );
    
            $timezone = $config->get('app_timezone', 'US/Eastern');
            date_default_timezone_set($timezone);
    
    Routes

    Our routes are stored in the base.php. Additional routes can be set in the config.php. The router is not initialized if this is a CLI application.

            /**
             * Routes
             */
            if (!K_CLI) {
                $di->set(
                    'router',
                    function () use ($config) {
                        $router = new Router(false);
                        $router->removeExtraSlashes(true);
                        $routes = $config->routes->toArray();
                        foreach ($routes as $pattern => $options) {
                            $router->add($pattern, $options);
                        }
    
                        return $router;
                    },
                    true
                );
            }
    
    Dispatcher

    The dispatcher is instantiated with a listener, attaching to the beforeException event of the dispatcher. A custom plugin NotFoundPlugin is used to send output to the 404 page. Using the plugin allows us to reuse it anywhere in the application. This implementation is very beneficial when developing multi module applications.

    NOTE: For the CLI application later on, we will need the CLI dispatcher.

            /**
             * We register the events manager
             */
            $di->set(
                'dispatcher',
                function () use ($di) {
                    $eventsManager = new EventsManager;
    
                    /**
                     * Handle exceptions and not-found exceptions using NotFoundPlugin
                     */
                    $eventsManager->attach('dispatch:beforeException', new NotFoundPlugin);
    
                    $dispatcher = new Dispatcher;
                    $dispatcher->setEventsManager($eventsManager);
    
                    $dispatcher->setDefaultNamespace('Kitsune\Controllers');
    
                    return $dispatcher;
                }
            );
    
    Views

    The views are being initialized using Volt as the template engine. The main view is set up with the expected options.

            $di->set(
                'view',
                function () use ($config) {
                    $view = new View();
                    $view->setViewsDir(K_PATH . '/app/views/');
                    $view->registerEngines([".volt" => 'volt']);
                    return $view;
                }
            );
    
            /**
             * Setting up volt
             */
            $di->set(
                'volt',
                function ($view, $di) {
                    $volt = new VoltEngine($view, $di);
                    $volt->setOptions(
                        [
                            "compiledPath"  => K_PATH . '/var/cache/volt/',
                            'stat'          => K_DEBUG,
                            'compileAlways' => K_DEBUG,
                        ]
                    );
                    return $volt;
                },
                true
            );
    
    Cache

    The cache component is configured using the config.php. We can define the parameters in that file and thus use say the File cache for our local/development machine and a more advanced cache (Memcached for instance) for the production system.

            /**
             * Cache
             */
            $frontConfig = $config->cache_data->front->toArray();
            $backConfig  = $config->cache_data->back->toArray();
            $class       = '\Phalcon\Cache\Frontend\\' . $frontConfig['adapter'];
            $frontCache  = new $class($frontConfig['params']);
            $class       = '\Phalcon\Cache\Backend\\' . $backConfig['adapter'];
            $cache       = new $class($frontCache, $backConfig['params']);
            $di->set('cache', $cache, true);
    
            /**
             * viewCache
             */
            $frontConfig = $config->cache_view->front->toArray();
            $backConfig  = $config->cache_view->back->toArray();
            $class       = '\Phalcon\Cache\Frontend\\' . $frontConfig['adapter'];
            $frontCache  = new $class($frontConfig['params']);
            $class       = '\Phalcon\Cache\Backend\\' . $backConfig['adapter'];
            $cacheView   = new $class($frontCache, $backConfig['params']);
            $di->set('viewCache', $cacheView, true);
    
    Markdown Renderer

    We use Ciconia for the rendering of markdown with several plugins, existing and user defined. The registration is pretty straight forward.

            /**
             * Markdown renderer
             */
            $di->set(
                'markdown',
                function () {
                    $ciconia = new Ciconia();
                    $ciconia->addExtension(new FencedCodeBlockExtension());
                    $ciconia->addExtension(new TaskListExtension());
                    $ciconia->addExtension(new InlineStyleExtension());
                    $ciconia->addExtension(new WhiteSpaceExtension());
                    $ciconia->addExtension(new TableExtension());
                    $ciconia->addExtension(new UrlAutoLinkExtension());
                    $ciconia->addExtension(new MentionExtension());
    
                    $extension = new IssueExtension();
                    $extension->setIssueUrl(
                        '[#%s](https://github.com/phalcon/cphalcon/issues/%s)'
                    );
                    $ciconia->addExtension($extension);
    
                    $extension = new PullRequestExtension();
                    $extension->setIssueUrl(
                        '[#%s](https://github.com/phalcon/cphalcon/pull/%s)'
                    );
                    $ciconia->addExtension($extension);
                    return $ciconia;
                },
                true
            );
    
    Posts Finder

    This is a class we came up with, which is used to give us an easy way to get information about a specific post, the tag cloud, the index page etc. It is utilizing cache a lot!

            /**
             * Posts Finder
             */
            $di->set(
                'finder',
                function () use ($utils, $cache) {
                    $key        = 'post.finder.cache';
                    $postFinder = $utils->cacheGet($key);
                    if (null === $postFinder) {
                        $postFinder = new PostFinder();
                        $cache->save($key, $postFinder);
                    }
                    return $postFinder;
                },
                true
            );
    

    Conclusion

    In the next post of these series we will take a look at the router and discuss what each route means to our application.

    Comments are more than welcome. If you have any questions on the implementation, feel free to ask in the comments below.

    References

  • 2010-02-02 12:00:00

    Design Patterns - Factory

    A note about these series. It appears that Giorgio Sironi and I had the same idea regarding Design Patterns and blogging about them. He covers the Factory design pattern thoroughly in his blog post, which is recommended reading.

    The Problem

    I started off my IT career as a network administrator. This was back in the good old Novell 3.11 days. After that it was Novell 4.0, Microsoft Servers etc. Following that I got more and more involved with Visual Basic and when Microsoft decided to move everyone to .NET I chose not to follow and ended up coding in PHP.

    Since my programming knowledge came from within (studying, reading articles, trial and error), the problems that I was facing on a daily basis are the same as almost every developer faces. One particularly challenging problem that I had in the VB days as well as the PHP days was repetition of code and how to eliminate it.

    When I started programming for the Ferrari Fans Fun Forecast site I was running the site using my apartment's ADSL line. In the beginning there were only 20 users or so, therefore that setup was fine. The scripts were VBScript against a local instance of Microsoft SQL Server. Later on though, I switched to PHP while keeping Microsoft SQL Server.

    Initial implementation

    I knew that I would have to change my scripts later on to work against MySQL since I was to change the hosting of the site. Through laziness or poor design (you can pick either or both :)) I chose to create a class for Microsoft SQL and later on I would just change it to the MySQL. It seemed the easiest thing to do at the time.

    So my class was something like:

     class DbMSSQL
    {
        private $_conn = null;
    
        public function connect()
        {
            // Connect
            // This is where we have the connection parameters
            include_once 'connection.inc.php';
    
            $this->_conn = mssql_connect($host, $user, $password);
            if (!$this->_conn) {
                throw new Exception('Cannot connect to the database.');
            }
        }
    
        public function disconnect()
        {
             // Disconnect
            mssql_close($this->_conn);
        }
    
        public function selectdb()
        {
             // Select the db
            $db = mssql_select_db($database, $this->_conn);
            if (!$db) {
                throw new Exception('Cannot select the database');
            }
        }
    
        public function query($sql)
        {
         // Query the db
            $_result = mssql_query($sql);
    
            if (!$_result) {
                throw new Exception('Error in query : ' . $sql);
            }
    
            $data = array();
    
            while ($row = mssql_fetch_assoc($_result)) {
                $data[$row['id']] = $row;
            }
    
            mssql_free_result($_result);
    
            return $data;
        }
    }
    

    Everything worked fine so I did not worry about a thing. A few months later though I was forced to move the database (as I expected) to MySQL. I could not move everything in one go so I had to move some of the tables initially and a week later everything else.

    To tackle this requirement I created a second class to handle operations against MySQL. The class that I ended up with was:

    class DbMySQL
    {
        private $_conn = null;
    
        public function connect()
        {
            // Connect
            // This is where we have the connection parameters
            include_once 'connection.inc.php';
    
            $this->_conn = mysql_connect($host, $user, $password);
            if (!$this->_conn) {
                throw new Exception('Cannot connect to the database :' . mysql_error());
            }
        }
    
        public function disconnect()
        {
             // Disconnect
            mysql_close($this->_conn);
        }
    
        public function selectdb()
        {
             // Select the db
            $db = mysql_select_db($database, $this->_conn);
            if (!$db) {
                throw new Exception('Cannot select the database : ' . mysql_error());
            }
        }
    
        public function query($sql)
        {
         // Query the db
            $_result = mysql_query($sql);
    
            if (!$_result) {
                throw new Exception('Error in query : ' . mysql_error() . "\n" . $sql);
            }
    
            $data = array();
    
            while ($row = mysql_fetch_assoc($_result)) {
                $data[$row['id']] = $row;
            }
    
            mysql_free_result($_result);
    
            return $data;
        }
    }
    

    You can easily see the problem here. There is a lot of repetition in the code, not so much as the actual method properties but the methods themselves. Both classes have connect(), disconnect(), selectdb() and query() as methods. In reality the code changes only slightly since the call for an operation against Microsoft SQL Server is mssql_* while for MySQL is mysql_*. During the transition week I was in programming hell. At some point I mixed the class names, I was trying to read and update the wrong server etc. (see Jani Hartikainen's post about 6 programming project mistakes you should avoid - I did all that!).

    That week though taught me that I need to pay more attention in designing rather than going full speed ahead with programming and later on paying the consequences.

    After thorough research, I discovered a library that would support both platforms. The library that I found was ADOdb which is a perfect example of the Factory Pattern. I used that library later on for a different project, but just looking at the code and understanding the flow of operations as well as the implementation of the pattern itself was invaluable to me.

    Interfaces

    First of all I need to explain what an interface is and why we need them. According to PHP.net:

    Object interfaces allow you to create code which specifies which methods a class must implement, without having to define how these methods are handled.

    So imagine an interface something like a graft, a blueprint on what I need to construct. The Interface will have the common methods and properties that I need to implement.

    When dealing with database connections to two different database servers (Microsoft SQL Server and MySQL), I can clearly define a few methods that will follow CRUD (Create, Read, Update, Delete). Those are:

    • Connect to the database server
    • Select database
    • Insert record
    • Delete record
    • Update record
    • Select record(s)
    • Close connection to the database server

    My interface would therefore be:

    interface iDatabase
    {
        public function connect();
        public function disconnect();
        public function selectdb();
        public function query($sql);
    }
    

    Design Patterns - Factory

    A class implementing the Factory Pattern is like a car manufacturing plant producing three different cars on the same assembly line. All cars have common characteristics like 4 wheels, 4 doors (well most of them), a steering wheel, a dashboard etc. and all of them perform certain operations i.e. drive, reverse etc.

    In my problem earlier I could have used the Factory Pattern to create one class that would have implemented my blueprint, the interface which defines the CRUD operations that I need. So based on the above, the implementation will result in three classes.

    MSSQL class - stored in the file Db_mssql.php
    class Db_mssql implements iDatabase
    {
        private $_conn = null;
    
        public function connect()
        {
            // Connect
            // This is where we have the connection parameters
            include_once 'connection.inc.php';
    
            $this->_conn = mssql_connect($host, $user, $password);
            if (!$this->_conn) {
                throw new Exception('Cannot connect to the database.');
            }
        }
    
        public function disconnect()
        {
             // Disconnect
            mssql_close($this->_conn);
        }
    
        public function selectdb()
        {
             // Select the db
            $db = mssql_select_db($database, $this->_conn);
            if (!$db) {
                throw new Exception('Cannot select the database');
            }
        }
    
        public function query($sql)
        {
         // Query the db
            $_result = mssql_query($sql);
    
            if (!$_result) {
                throw new Exception('Error in query : ' . $sql);
            }
    
            $data = array();
    
            while ($row = mssql_fetch_assoc($_result)) {
                $data[$row['id']] = $row;
            }
    
            mssql_free_result($_result);
    
            return $data;
        }
    }
    
    MySQL class - stored in the file Db_mysql.php
    class Db_mysql implements iDatabase
    {
        private $_conn = null;
    
        public function connect()
        {
            // Connect
            // This is where we have the connection parameters
            include_once 'connection.inc.php';
    
            $this->_conn = mysql_connect($host, $user, $password);
            if (!$this->_conn) {
                throw new Exception('Cannot connect to the database :' . mysql_error());
            }
        }
    
        public function disconnect()
        {
             // Disconnect
            mysql_close($this->_conn);
        }
    
        public function selectdb()
        {
             // Select the db
            $db = mysql_select_db($database, $this->_conn);
            if (!$db) {
                throw new Exception('Cannot select the database : ' . mysql_error());
            }
        }
    
        public function query($sql)
        {
         // Query the db
            $_result = mysql_query($sql);
    
            if (!$_result) {
                throw new Exception('Error in query : ' . mysql_error() . "\n" . $sql);
            }
    
            $data = array();
    
            while ($row = mysql_fetch_assoc($_result)) {
                $data[$row['id']] = $row;
            }
    
            mysql_free_result($_result);
    
            return $data;
        }
    }
    

    Notice that both these classes are almost identical to the initial implementation shown earlier in this post. The only difference is that they are both implementing the iDatabase interface.

    So what is different now? The class that implements the Factory Pattern.

    class Db
    {
        public static function factory($type)
        {
            $fileName = 'Db_' . strtolower($type) . '.php';
            if (!file_exists($fileName)) {
                throw new Exception('File not found : ' . $fileName);
            }
    
            $className = 'Db_' . strtolower($type);
    
            return new $className;
        }
    }
    

    What this class does now is it allows me to load the relevant database connection class on the fly. If I want a Microsoft SQL connection I would call:

        $mssql = Db::factory('mssql');
    

    while for MySQL the command becomes:

        $mysql = Db::factory('mysql');
    

    Again since both underlying classes implement the iDatabase interface, I know exactly what to expect as far as methods and functionality is concerned from each class.

    Conclusion

    The Factory Design Pattern is one of the most powerful design patterns. It provides 'decoupling' i.e. breaks the inherited dependency of a class and its subclasses. It also allows for great flexibility while keeping the same interface for your clients.

    Zend Framework uses the Factory Pattern in Zend_Db. Specifically the example on the site shows:

    // We don't need the following statement because the
    // Zend_Db_Adapter_Pdo_Mysql file will be loaded for us by
    // the Zend_Db factory method.
    
    // require_once 'Zend/Db/Adapter/Pdo/Mysql.php';
    
    // Automatically load class Zend_Db_Adapter_Pdo_Mysql
    // and create an instance of it.
    $db = Zend_Db::factory(
        'Pdo_Mysql', 
        array(
            'host'     => '127.0.0.1',
            'username' => 'webuser',
            'password' => 'xxxxxxxx',
            'dbname'   => 'test'
        )
    );
    

    The Zend_Db factory accepts the name of the adapter used for the database connection as the first parameter while the second parameter is an array with connection specific information. With the use of the Factory Pattern, Zend_Db exposes a common interface which allows programmers to connect to a number of databases using the same methods. Should in the future the application needs to access a different database, the impact to the developer is minimal - in most cases a change to the adapter name (first parameter of the factory class) is all it takes.

  • 2010-01-22 12:00:00

    Design Patterns - Singleton

  • 2010-01-06 12:00:00

    Design Patterns in PHP Series

    A lot of developers – including myself – have at some point in their programming careers found themselves repeating a task that they have completed for a previous project or for a previous part of the same project.

    This problem of repeating code is solved by design patterns. A design pattern is the way that the code must be structured so that the problem at hand can be solved. The characteristics of design patterns are:

    • Name – it lets other programmers know what this pattern does.
    • Problem – where the pattern can be applied
    • Solution – how this pattern is implemented

    In the course of the next few weeks, I will publish a series of blog posts, where I will try to present you with some common design patterns and how I have understood their use. Most books and online materials concentrate on just presenting the issue at hand and do not focus on how we ended up there. In these blog post series I will try to show you what I found along the way and how I solved each problem in turn.

    As usual comments are more than welcome.

    The design patterns I will discuss in posts of these series are as:

    • Singleton Pattern
    • Factory Pattern
    • Registry Pattern
    • Decorator Pattern
    • Adapter Pattern
    • Iterator Pattern
    • Strategy Pattern
    • Active Record Pattern
    • Value Object Pattern
    • Model View Controller Pattern
    • MockObject Pattern
    • Observer Pattern
    • Proxy Pattern
    • Table Data Gateway Pattern
    • Data Mapper Pattern

    You can check this blog every week, subscribe to the RSS feed, follow me on Twitter or follow my Google Reader (or all of the above).