Including an Attribute Type in a Package

If you haven't, check out the documentation on packaging a theme. Here you'll learn the ins and outs on the Concrete CMS package format, a package's controller file and get up to speed quickly.

Once you have your package's controller file created, it's a simple matter to add support for your custom attribute type to the package. Let's take our Property Location custom attribute type and place it in a package named Property Manager, with the package handle property_manager.

First, create an attributes directory within your package's directory.

mkdir packages/property_manager
mkdir packages/property_manager/attributes/

Now, let's move the entities that we've created. They're not going to be in the application/src directory any longer. Move them from application/src/Entity to packages/property_manager/src/Concrete/Entity, and make sure to change their namespaces from PropCo\Property\Location to Concrete\Package\PropertyManager\Entity everywhere the classes are used.

Next, create a controller file for your package as per the theming instructions listed above. Move your property_location custom attribute type from application/attributes/property_location into the package.

mv application/blocks/property_location packages/property_manager/attributes/property_location

Then, in your package's install() method, use the controller $app method (which is an instance of the Concrete\Core\Application\Application method to instantiate the Concrete\Core\Attribute\TypeFactory class.

public function install()
{
    $pkg = parent::install();
    $factory = $this->app->make('Concrete\Core\Attribute\TypeFactory');
    $type = $factory->getByHandle('property_location');
    if (!is_object($type)) {
        $type = $factory->add('property_location', 'Property Location', $pkg);
    }       
}

That's it! Your type now exists. Now, you'll want to ensure that it is usable from within the core attribute categories that you care about. These are pages, files and users. For our purposes, we only want to make sure that you can add these attribute types to pages, so let's add this code for associating this attribute type to the page attribute category:

$service = $this->app->make('Concrete\Core\Attribute\Category\CategoryService');
$category = $service->getByHandle('collection')->getController();
$category->associateAttributeKeyType($type);

That's it. $service->getByHandle('collection') returns an instance of the Concrete\Core\Entity\Attribute\Category object, which is a generic category entity object. In order to get the class that can actually perform operations on the category (The Concrete\Core\Attribute\Category\PageCategory class) you'll need to run getController on that generic entity object.