The concrete5 package format is a way to bundle most aspects of concrete5 functionality together, so that they can be easily distributed, installed and uninstalled. The package format is used by the concrete5 marketplace, but can also be used without connecting to concrete5.org.

Available Components

The following items may be bundled into a package:

  • Libraries
  • Models
  • Elements
  • Tools
  • Block Types
  • Page Types
  • Page Controllers
  • Single Pages
  • Mail Helpers
  • Mail Importers
  • Attribute Keys
  • Attribute Categories
  • Attribute Types
  • Attribute Sets
  • Dashboard Modules
  • Configuration Values
  • Themes
  • Task Permissions
  • Jobs

What are Packages?


Of one of the things that make concrete5 really unique is its ability to package up reusable components to be instantly installable on another concrete5 website. Packages can basically be anything, like blocks, themes, templates, or full applications (such as ad server app or calendar app).

You might choose to create packages just to speed development on own projects. But if it’s something really cool that other's might like, and it plays well with other add-ons, you can release it on the concrete5 marketplace. And as of the 5.3 release, packages that are added to the marketplace can be remotely downloaded and installed on a concrete5 website directly from the dashboard (no ftp or programming skills required). You can make your package available either as a free download, or you can make some money by selling it. Read the marketplace rules and submit your package when it's ready.

Note: If you’re looking for instructions on how to create a block, application, or theme, check out the developer docs. This is document only describes how to package existing components that you've already made.
 

Package File & Folder Structure


The structure of folders and files within a concrete5 package closely mirrors the folder structure of the root concrete folder. For example, let’s say we’re packaging up an already created “Hello World” block (downloadable below). First you’d create a folder called hello_world in the packages directory, and within that you’d add a blocks folder that would contain your hello_world block:

packages_hello_world_folder_structure.png
Figure 1.

Within the package root folder you only need a one file, controller.php, which is discussed below. The icon.png is a unique 97x97 image with transparent corners used to represent your package within the concrete5 marketplace (note that this is different from the 16x16 icon.png within the blocks folder).  CHANGELOG is just a text file used to keep track of the package versions.

The folder structure of a more complex application may include some of the other standard concrete root folders. For example, here is the folder structure of the larger calendar application, containing blocks, controllers, models, etc:

packages_calendar_folder_structure.png
Figure 2.

The Package Controller:


Every package has a controller.php file in its base directory. This file only contains the information needed for your system to identify the package and to install it. All other logic relating to what your package actually does should be located elsewhere. The package controller file is pretty straightforward:

defined('C5_EXECUTE') or die(_("Access Denied."));

class HelloWorldPackage extends Package {

     protected $pkgHandle = 'hello_world';
     protected $appVersionRequired = '5.3.0';
     protected $pkgVersion = '1.0';

     public function getPackageDescription() {
          return t("Just an example package that says Hello World.");
     }

     public function getPackageName() {
          return t("Hello World");
     }
     
     public function install() {
          $pkg = parent::install();
     
          // install block 
          BlockType::installBlockTypeFromPackage('hello_world', $pkg); 
     }
     
}



There are a few things to watch out for here. To add your package to the concrete5 marketplace, it has to have a unique handle. The handle should be exactly the same as the package folder (in this case hello_world). The controller class name should contain the uppercased version of your package handle, with no spaces, and “Package” appended at the end. So in this case the hello_world package handle becomes HelloWorldPackage. If you name you package wrong, it won’t install, or it won’t be able to locate the package controller. As a general naming convention, if you are packaging a theme, please make it start with “theme_” (like theme_natural_essence).

Package::getPackageName()

and

Package::getPackageDescription() 

are simply there to identify your package during installation. If you are releasing your package to the marketplace, please include all text in the t(“Some Text”) translation function, as this will allow your block to be ported over to other languages much easier.

Package::install() is required in almost all package types (with the exception of packaged templates). What’s inside of your install function really depends on what kind of package you’re installing. In this HelloWorld package, all we need to install is the HelloWorld block, which just happens to have the same handle as the package (not required, but it’s a good idea since it helps to prevent conflicts):

BlockType::installBlockTypeFromPackage('hello_world', $pkg);



If you were packaging up a theme, you’d just need this line to install the theme instead:

PageTheme::add('dreamy', $pkg);



For more complex package installations, you can use this install method to add Pages, PageTypes, Groups, PageAttributes, etc. You may want to look at concrete/controllers/install controllers

InstallController::configure() 

method for examples on how to perform some of these advanced tasks. Packages also allow you to include a db.xml file in the package root, however, if you’re just packaging up a block, you’ll just need the one db.xml file in your blocks directory as shown in figure 1.

Package Installation:



So once your package is complete, there’s just one step left, which is running the installation. (BTW, when installing your package for the first time, you should probably try it out on a testing installation of concrete5). Login to your website, go to the “Add Functionality” page of the dashboard, and your package should be listed under the “New” column, ready for you to install it. Hopefully the installation will work fine, but if something goes wrong you might have to delete the package from the Packages table in your database to retry the installation.

This documentation page was written by Tony Trupp.

If you’ve got any questions directly relating to packaging up components you’ve made, this is the place to ask. Specific questions about how blocks, themes, or something specific to your app should be posted to the forums.

Recent Discussions on this Topic

Package installers

Just getting up to speed on packages here. If you have a functionality that depends upon an event, say page load or content publish, etc, then don't you need to ensure that the site.php config line of: define('ENABLE_APPLICATION_EVENTS', true); …

Package file run precedents

I have a package and I want one of its controllers methods to run before 'config/base.php' runs. I would also be satisfied if I could get one of that packages files to load before 'config/base.php'. Is this at all possible?

Page type controller cannot be loaded from package

The controller I created could not be detected after I placed it in a package, however when placed on the outer directories of C5 it could be detected. Do I need to put something on the package controller so it would be able to detect it?

Customising packages

I bought a package from the marketplace and it gets me 95% to my target goal. The remainder I need to do myself through customisations. In a similar vein to the concrete5 core, is there a proposed way that you can override packages and the code within?…