





















































Create and customize your own website with the Concrete5 Beginner's Guide
Before we start creating our package, here are a few words about the functionality and purpose of packages:
These are the most important things you can do with a package; some of it doesn't depend on packages, but is easier to handle if you use packages. It's up to you, but putting every extension in a package might even be useful if there's just a single element in it—why?
We've already looked at different structures and you are probably already familiar with most of the directories in concrete5. Before we continue, here are a few words about the package structure, as it's essential that you understand its concept before we continue.
A package is basically a complete concrete5 structure within one directory. All the directories are optional though. No need to create all of them, but you can create and use all of them within a single package. The directory concrete is a lot like a package as well; it's just located in its own directory and not within packages.
Like the blocks we've created, the package has a controller as well. First of all, it is used to handle the installation process, but it's not limited to that. We can handle events and a few more things in the package controller; there's more about that later in this article.
For now, we only need the controller to make sure the dashboard knows the package name and description.
Carry out the following steps:
<?php
defined('C5_EXECUTE') or die(_("Access Denied."));
class c5bookPackage extends Package {
protected $pkgHandle = 'c5book';
protected $appVersionRequired = '5.4.0';
protected $pkgVersion = '1.0';
public function getPackageDescription() {
return t("Theme, Templates and Blocks from
concrete5 for Beginner's");
}
public function getPackageName() {
return t("c5book");
}
public function install() {
$pkg = parent::install();
}
}
?>
The controller we created looks and works a lot like a block controller, which you should have seen and created already. However, let's go through all the elements of the package controller anyway, as it's important that you understand them:
Remember the templates we've created? We placed them in the top level blocks directory. Worked like a charm but imagine what happens when you create a theme which also needs some block templates in order to make sure the blocks look like the theme? You'd have to copy files into the blocks directory as well as themes. This is exactly what we're trying to avoid with packages.
It's rather easy with templates; they work almost anywhere. You just have to copy the folder slideshow from blocks to packages/c5book/blocks, as shown in the following screenshot:
This step was even easier than most things we did before. We simply moved our templates into a different directory—nothing else.
concrete5 looks for custom templates in different places like:
It doesn't matter where you put your templates, concrete5 will find them.
Now that we've got our templates in the package, let's move the new blocks we've created into that package as well. The process is similar, but we have to call a method in the installer which installs our block. concrete5 does not automatically install blocks within packages.
This means that we have to extend the empty install method shown earlier.
Before we move the blocks into the package you should remove all blocks first. To do this, go to your dashboard, click on Add Functionality, click on the Edit button next to the block you want to move, and click on the Remove button in the next screen. We'll start with the jqzoom block.
Please note; removing a block will of course, remove all the blocks you've added to your pages. Content will be lost if you move a block into a package after you've already used it.
Carry out the following steps:
public function install() {
$pkg = parent::install();
// install blocks
BlockType::installBlockTypeFromPackage('jqzoom', $pkg);
}
Besides moving files, we only had to add a single line of code to our existing package controller. This is necessary, because blocks within packages aren't automatically installed. When installing a package, only the install method of the controller is called, exactly the place where we hook into and install our block.
The installBlockTypeFromPackage method takes two parameters: The block handle and the package object. However, this doesn't mean that packages behave like namespaces. What does this mean?
You've seen that we had to remove and reinstall the package several times while we only moved a block. At this point, it probably looks a bit weird to do that, especially as you're going to lose some content on your website.
However, when you're more familiar with the concrete5 framework, you'll usually know if you're going to need a package and make that decision before you start creating new blocks. If you're still in doubt, don't worry about it too much and create a package and not just a block. Using a package is usually the safest choice.
Don't forget that all instances of a block will be removed from all pages when you uninstall the block from your website. Make sure your package structure doesn't change before you start adding content to your website.
Some blocks depend on helpers, files and libraries, which aren't in the block directory. The PDF generator block is such an example. It depends on a file found in the tools directory in the root of your concrete5 website. How do we include such a file in a package?
<?php
defined('C5_EXECUTE') or die(_("Access Denied."));
Loader::library('mpdf50/mpdf', 'c5book');
$fh = Loader::helper('file');
$header = <<<EOT
<style type="text/css">
body { font-family: Helvetica, Arial; }
h1 { border-bottom: 1px solid black; }
</style>
EOT;
<!--hidden_in_pdf_start-->
<?php
defined('C5_EXECUTE') or die(_('Access Denied.'));
$nh = Loader::helper('navigation');
$url = Loader::helper('concrete/urls');
$toolsUrl = $url->getToolsURL('generate_pdf', 'c5book');
$toolsUrl .= '?p=' . rawurlencode($nh->getLinkToCollection($this-
>c, true));
echo "<a href="{$toolsUrl}">PDF</a>";
?>
<!--hidden_in_pdf_end-->
In the preceding example, we put got a file in the tools directory and a PDF generator in the libraries directory, which we had to move as well.
Even at the risk of saying the same thing several times: A package can contain any element of concrete5—libraries, tools, controllers, images, and so on. By putting all files in a single package directory, we can make sure that all files are installed at once, thus making sure all dependencies are met.
Nothing has changed beside the small changes we've made to the commands, which access or load an element. A helper behaves like a helper, no matter where it's located.
We've moved two different blocks into our new package, along with the slideshow block templates. These aren't all blocks we've created so far. Try to move all add-ons we've created into our new package. If you need more information about that process, have a look at the following page:
http://www.concrete5.org/documentation/developers/system/packages/