Perforce Chronicle 2012.2/486814
API Documentation

P4Cms_Content_Type Class Reference

Provides storage of content type definitions. More...

Inheritance diagram for P4Cms_Content_Type:
P4Cms_Record P4Cms_Record_Connected P4Cms_Model P4Cms_ModelInterface

List of all members.

Public Member Functions

 delete ($description=null)
 Delete this record.
 getAddUri ()
 Get the URI to add content of this type.
 getContentCount ($includeDeleted=false)
 Get the number of content entries of this type.
 getDescription ()
 Get the current description.
 getDisplayDecorators ($element)
 Get the display decorators for a given element.
 getDisplayFilters ($element)
 Get the display/output filters for a given element.
 getElement ($element)
 Get the named element for this content type.
 getElementNames ()
 Get the names of all elements in this type.
 getElements ()
 Get the elements that make up this content type.
 getElementsAsIni ()
 Get the elements in INI format.
 getFormElement ($element)
 Get the named element as a form element.
 getFormElements ()
 Get all of the content type elements as form elements.
 getGroup ()
 Get the current group.
 getIcon ()
 Get the current icon.
 getLabel ()
 Get the current label.
 getLayout ()
 Get the layout script to use.
 getValidationErrors ()
 Accessor for validation errors.
 hasElement ($name)
 Determine if this type has the given element name.
 hasIcon ()
 Determine if this type has an icon to display.
 hasValidElements ()
 Determine if the elements are valid for use in a form and a content type record.
 save ($description=null)
 Save this record.
 setDescription ($description)
 Set a new description.
 setElements ($elements)
 Set the elements that make up this content type.
 setElementsFromIni ($elements)
 Set the elements in INI format.
 setGroup ($group)
 Set a new group.
 setIcon ($icon)
 Set a new icon.
 setIconFromFile ($file)
 Uses one method rather than two to set the icon for a content type.
 setId ($id)
 Set the id of the content type.
 setLabel ($label)
 Set a new label.
 setLayout ($layout)
 Set the layout script to use.
 validateElements ()
 Validate the element for use in a form and a content type record.

Static Public Member Functions

static fetchGroups (P4Cms_Record_Adapter $adapter=null)
 Get a list of all known content types indexed by group name.
static installDefaultTypes (P4Cms_Record_Adapter $adapter=null, $clobberDeleted=false)
 Collect all of the default content types and install any that are missing.
static installPackageDefaults (P4Cms_PackageAbstract $package, P4Cms_Record_Adapter $adapter=null, $clobberDeleted=false)
 Install the default content types contributed by a package.
static removePackageDefaults (P4Cms_PackageAbstract $package, P4Cms_Record_Adapter $adapter=null)
 Remove content types contributed by a package.

Protected Attributes

 $_elements = null
 $_form = null
 $_hasValidElements = null
 $_validationErrors = array()

Static Protected Attributes

static $_fields
 Specifies the array of fields that the current Record class wishes to use.
static $_fileContentField = 'elements'
 Specifies the name of the record field which will be persisted in the file used to store the records.
static $_storageSubPath = 'content-types'
 Specifies the sub-path to use for storage of records.

Detailed Description

Provides storage of content type definitions.

Copyright:
2011-2012 Perforce Software. All rights reserved
License:
Please see LICENSE.txt in top-level folder of this distribution.
Version:
2012.2/486814

Member Function Documentation

P4Cms_Content_Type::delete ( description = null)

Delete this record.

Parameters:
string$descriptionoptional - a description of the change.
Returns:
P4Cms_Record provides fluent interface.

Reimplemented from P4Cms_Record.

    {
        P4Cms_Content::clearTypeCache($this->getAdapter());

        return parent::delete($description);
    }
static P4Cms_Content_Type::fetchGroups ( P4Cms_Record_Adapter adapter = null) [static]

Get a list of all known content types indexed by group name.

Parameters:
P4Cms_Record_Adapter$adapteroptional - storage adapter to use.
Returns:
array array, keyed on group name with P4Cms_Model_Iterator (containing Type models) for values.
    {
        // grab all entries
        $entries = static::fetchAll($adapter);

        // sort the entries by 'order' first, 'group' second and 'label' third.
        $entries->sortBy(
            array(
                'order' => array(P4Cms_Model_Iterator::SORT_NUMERIC),
                'group' => array(P4Cms_Model_Iterator::SORT_NATURAL),
                'label' => array(P4Cms_Model_Iterator::SORT_NATURAL)
            )
        );

        // loop entries and index by group
        $groups = array();
        foreach ($entries as $entry) {
            $group = $entry->getValue("group");

            if (!isset($groups[$group])) {
                $groups[$group] = new P4Cms_Model_Iterator;
            }

            $groups[$group][] = $entry;
        }

        return $groups;
    }
P4Cms_Content_Type::getAddUri ( )

Get the URI to add content of this type.

Returns:
string the URI to add content of this type.
    {
        $content = new P4Cms_Content;
        $content->setContentType($this);

        return $content->getUri('add');
    }
P4Cms_Content_Type::getContentCount ( includeDeleted = false)

Get the number of content entries of this type.

Parameters:
boolean$includeDeletedoptional - include deleted content entries
Returns:
integer the number of content entries of this type
    {
        // create a query to find all content entries of this type
        $filter = new P4Cms_Record_Filter;
        $filter->add('contentType', $this->getId(), P4Cms_Record_Filter::COMPARE_EQUAL);
        $query = new P4Cms_Record_Query();
        $query->addFilter($filter);

        if ($includeDeleted) {
            $query->setIncludeDeleted($includeDeleted);
        }

        return P4Cms_Content::count($query, $this->getAdapter());
    }
P4Cms_Content_Type::getDescription ( )

Get the current description.

Returns:
string|null The current description or null.
    {
        return $this->_getValue('description');
    }
P4Cms_Content_Type::getDisplayDecorators ( element)

Get the display decorators for a given element.

Display decorators can be specified for each element in the content type. If no display decorators have been explicitly set in the element definition, the method will look for default decorators on the form element.

If the form element implements the display decorators interface, the decorators will be taken from getDefaultDisplayDecorators().

Parameters:
string | Zend_Form_Element$elementelement name or instance to get decorators for.
Returns:
array the display decorators for the given element.
    {
        // element can be given as a string or an instance.
        if ($element instanceof Zend_Form_Element) {
            $formElement = clone $element;
            $element     = $formElement->getName();
        } else {
            $formElement = clone $this->getFormElement($element);
        }

        $decorators = array();
        $definition = $this->getElement($element);

        // always start with the value decorator.
        $formElement->setDecorators(array('Value'));

        // check for explicit decorators on the element definition.
        if (isset($definition['display']['decorators'])
            && is_array($definition['display']['decorators'])
        ) {
            $decorators = $definition['display']['decorators'];
            try {
                return $formElement->addDecorators($decorators)
                                   ->getDecorators();
            } catch (Exception $e) {
                P4Cms_Log::log(
                    "Failed to get user-specified decorators for field '"
                    . $element . "' in type '" . $this->getId() . "'.",
                    P4Cms_Log::ERR
                );
            }
        }

        // no explicit decorators, check for defaults on the form element.
        if ($formElement instanceof P4Cms_Content_EnhancedElementInterface) {
            $decorators = $formElement->getDefaultDisplayDecorators();
            try {
                $formElement->addDecorators($decorators);
            } catch (Exception $e) {
                P4Cms_Log::log(
                    "Failed to get default decorators for field '"
                    . $element . "' in type '" . $this->getId() . "'.",
                    P4Cms_Log::ERR
                );
            }
        }

        // include a label decorator if showLabel is true.
        if (isset($definition['display']['showLabel'])
            && $definition['display']['showLabel']
        ) {
            $formElement->addDecorator('Label');
        }

        return $formElement->getDecorators();
    }
P4Cms_Content_Type::getDisplayFilters ( element)

Get the display/output filters for a given element.

Display filters can be specified for each element in the content type.

Parameters:
string$elementthe name of the element to get display filters for.
Returns:
array the filters for the named element.
    {
        $definition = $this->getElement($element);

        // early exit if no filters defined.
        if (!isset($definition['display']['filters'])
            || !is_array($definition['display']['filters'])
        ) {
            return array();
        }

        try {
            $formElement = clone $this->getFormElement($element);
            return $formElement->setFilters($definition['display']['filters'])
                               ->getFilters();
        } catch (Exception $e) {
            P4Cms_Log::log(
                "Failed to get user-specified filters for field '"
                . $element . "' in type '" . $this->getId() . "'.",
                P4Cms_Log::ERR
            );
        }

        return array();
    }
P4Cms_Content_Type::getElement ( element)

Get the named element for this content type.

Parameters:
string$elementThe name of the element to fetch.
Returns:
array the field details for the named element or an empty array.
    {
        $elements = $this->getElements();

        // return an empty array if invalid element specified
        if (!array_key_exists($element, $elements)) {
            return array();
        }

        return $elements[$element];
    }
P4Cms_Content_Type::getElementNames ( )

Get the names of all elements in this type.

Returns:
array list of all element names.
    {
        return array_keys($this->getElements());
    }
P4Cms_Content_Type::getElements ( )

Get the elements that make up this content type.

The field definitions array is based on the Zend Form elements configuration format. For convenience, you can call getFormElements() to get elements as form elements.

Returns:
array the list of elements (field definitions).
    {
        if ($this->_elements === null) {
            $elements = $this->_getValue('elements');

            // convert elements INI string to an array using Zend_Config_Ini
            // write elements to a temp file to facilitate Zend_Config_Ini parsing.
            $tempFile = tempnam(sys_get_temp_dir(), 'type');
            file_put_contents($tempFile, $elements);
            $config   = new Zend_Config_Ini($tempFile);
            $elements = $config->toArray();
            unlink($tempFile);

            $elements = is_array($elements) ? $elements : array();

            // need to push filter options down an extra level to work-around:
            // http://framework.zend.com/issues/browse/ZF-11102
            // also need to verify that element plugins are available
            $form = new P4Cms_Form;
            $elementLoader = $form->getPluginLoader(P4Cms_Form::ELEMENT);
            foreach ($elements as &$element) {
                foreach (array('options', 'display') as $type) {
                    if (isset($element[$type]['filters']) && is_array($element[$type]['filters'])) {
                        foreach ($element[$type]['filters'] as &$filter) {
                            if (isset($filter['options']) && is_array($filter['options'])) {
                                $filter['options'] = array($filter['options']);
                            }
                        }
                    }
                }

                // default to text if element type is invalid and
                // disable rendering so its only shown in form mode.
                if (is_array($element) && isset($element['type']) && !$elementLoader->load($element['type'], false)) {
                    $element['type'] = 'text';
                    if (!isset($element['display']) || !is_array($element['display'])) {
                        $element['display'] = array();
                    }
                    $element['display']['render'] = false;
                }
            }

            $this->_elements = $elements;
        }

        return $this->_elements;
    }
P4Cms_Content_Type::getElementsAsIni ( )

Get the elements in INI format.

Returns:
string the list of elements (field definitions) in INI format.
    {
        return $this->_getValue('elements');
    }
P4Cms_Content_Type::getFormElement ( element)

Get the named element as a form element.

Parameters:
string$elementthe name of the element to get as a form element.
Returns:
Zend_Form_Element the named element as a form element.
    {
        $elements = $this->getFormElements();

        if (!array_key_exists($element, $elements)) {
            throw new P4Cms_Content_Exception(
                "Cannot get form element. The requested element is not among the form elements."
            );
        }

        return $elements[$element];
    }
P4Cms_Content_Type::getFormElements ( )

Get all of the content type elements as form elements.

Returns:
array all of the type elements as form elements.
    {
        if (!$this->_form instanceof P4Cms_Form) {
            $this->_form = new P4Cms_Form;
            $this->_form->setElements($this->getElements());
        }

        return $this->_form->getElements();
    }
P4Cms_Content_Type::getGroup ( )

Get the current group.

Returns:
string|null The current group or null.
    {
        return $this->_getValue('group');
    }
P4Cms_Content_Type::getIcon ( )

Get the current icon.

Returns:
string|null The current icon or null.
    {
        return $this->_getValue('icon');
    }
P4Cms_Content_Type::getLabel ( )

Get the current label.

Returns:
string|null The current label or null.
    {
        return $this->_getValue('label');
    }
P4Cms_Content_Type::getLayout ( )

Get the layout script to use.

Returns:
string|null the name of the layout script to use.
    {
        return $this->_getValue('layout');
    }
P4Cms_Content_Type::getValidationErrors ( )

Accessor for validation errors.

Returns:
array the list of validation errors; an empty list means no errors have been recorded.
    {
        return $this->_validationErrors;
    }
P4Cms_Content_Type::hasElement ( name)

Determine if this type has the given element name.

Parameters:
string$namethe name of the element to check for.
Returns:
bool true if the given element is in this type.
    {
        return array_key_exists($name, $this->getElements());
    }
P4Cms_Content_Type::hasIcon ( )

Determine if this type has an icon to display.

Returns:
bool true if there is an icon, false otherwise.
    {
        $metadata = $this->getFieldMetadata('icon');
        return (strlen($this->getValue('icon')) &&
                isset($metadata['mimeType']));
    }
P4Cms_Content_Type::hasValidElements ( )

Determine if the elements are valid for use in a form and a content type record.

Returns:
bool true if valid for use with content and forms.
    {
        // validate fields on first call - flag should be reset when elements change.
        if ($this->_hasValidElements === null) {
            $errors = $this->validateElements();
        }

        return $this->_hasValidElements;
    }
static P4Cms_Content_Type::installDefaultTypes ( P4Cms_Record_Adapter adapter = null,
clobberDeleted = false 
) [static]

Collect all of the default content types and install any that are missing.

By default, types that already exist (even in deleted state) are ignored. If the clobberDeleted option is set then deleted types are re-installed.

Parameters:
P4Cms_Record_Adapter$adapteroptional - storage adapter to use.
bool$clobberDeletedoptional - re-install deleted types.
    {
        // clear the module/theme cache
        P4Cms_Module::clearCache();
        P4Cms_Theme::clearCache();

        // if no adapter given, use default.
        $adapter = $adapter ?: static::getDefaultAdapter();

        // get all enabled modules.
        $packages = P4Cms_Module::fetchAllEnabled();

        // add current theme to packages since it may provide content types.
        if (P4Cms_Theme::hasActive()) {
            $packages[] = P4Cms_Theme::fetchActive();
        }

        // install default content types for each package.
        foreach ($packages as $package) {
            static::installPackageDefaults($package, $adapter, $clobberDeleted);
        }
    }
static P4Cms_Content_Type::installPackageDefaults ( P4Cms_PackageAbstract package,
P4Cms_Record_Adapter adapter = null,
clobberDeleted = false 
) [static]

Install the default content types contributed by a package.

Parameters:
P4Cms_PackageAbstract$packagethe package whose content types will be installed
P4Cms_Record_Adapter$adapteroptional - storage adapter to use.
boolean$clobberDeletedoptional - re-install deleted types.
    {
        // if no adapter given, use default.
        $adapter = $adapter ?: static::getDefaultAdapter();

        $info = $package->getPackageInfo();

        // get the default types provided by the package
        $types = isset($info['types']) && is_array($info['types'])
               ? $info['types']
               : array();

        // control whether deleted types are ignored.
        $existsOptions = array('includeDeleted' => !$clobberDeleted);
        foreach ($types as $id => $type) {
            // skip the existing content type
            if (static::exists($id, $existsOptions, $adapter)) {
                continue;
            }

            $type['id']  = $id;
            $contentType = new P4Cms_Content_Type($type, $adapter);

            // set icon if any
            if (isset($type['iconFile'])) {
                $contentType->setIconFromFile(
                    $package->getPath() . '/resources/' . $type['iconFile']
                );
            }

            $contentType->save();
        }
    }
static P4Cms_Content_Type::removePackageDefaults ( P4Cms_PackageAbstract package,
P4Cms_Record_Adapter adapter = null 
) [static]

Remove content types contributed by a package.

The content types are only removed if it has not been changed and there does not exist any content entry of the type.

Parameters:
P4Cms_PackageAbstract$packagethe package whose content types is to be removed
P4Cms_Record_Adapter$adapteroptional - storage adapter to use.
    {
        // if no adapter given, use default.
        $adapter = $adapter ?: static::getDefaultAdapter();

        $info = $package->getPackageInfo();

        // get the default types provided by the package
        $types = isset($info['types']) && is_array($info['types'])
               ? $info['types']
               : array();

        foreach ($types as $id => $type) {
            $type['id']  = $id;
            $contentType = new P4Cms_Content_Type($type, $adapter);

            // delete the content type if it's not changed and
            // there is no content entries of this type
            if (static::exists($contentType->getId(), null, $adapter)
                && ($contentType->getContentCount() <= 0)
            ) {
                $storedType = static::fetch($id, null, $adapter);

                // check if the content type is different from the default
                if ($contentType->getValues() == $storedType->getValues()) {
                    $storedType->delete("Package '" . $package->getName() . "' disabled.");
                }
            }
        }
    }
P4Cms_Content_Type::save ( description = null)

Save this record.

Extends parent to clear P4Cms_Content's type cache.

Parameters:
string$descriptionoptional - a description of the change.
Returns:
P4Cms_Record provides a fluent interface
    {
        P4Cms_Content::clearTypeCache($this->getAdapter());
        return parent::save($description);
    }
P4Cms_Content_Type::setDescription ( description)

Set a new description.

Parameters:
string | null$descriptionThe new description to use.
Returns:
P4Cms_Content_Type To maintain a fluent interface.
    {
        if (!is_string($description) && !is_null($description)) {
            throw new InvalidArgumentException("Description must be a string or null.");
        }

        return $this->_setValue('description', $description);
    }
P4Cms_Content_Type::setElements ( elements)

Set the elements that make up this content type.

Parameters:
array | string | null$elementsthe list of elements (field definitions). if given as a string assumed to be INI format.
Returns:
P4Cms_Content_Type provides fluent interface.
    {
        if (!is_null($elements) && !is_array($elements) && !is_string($elements)) {
            throw new InvalidArgumentException(
                "Cannot set elements. Elements must be given as an array, string or null."
            );
        }

        // if elements given as string, assumed to be INI format.
        if (is_string($elements)) {
            return $this->setElementsFromIni($elements);
        }

        // if elements given as non-null, convert to INI
        if (!is_null($elements)) {
            // convert elements array to INI format.
            $config     = new Zend_Config($elements);
            $writer     = new Zend_Config_Writer_Ini();
            $elements   = $writer->setConfig($config)->render();
        }

        // reset elements.
        $this->_hasValidElements = null;
        $this->_elements         = null;
        $this->_form             = null;

        return $this->_setValue('elements', $elements);
    }
P4Cms_Content_Type::setElementsFromIni ( elements)

Set the elements in INI format.

Parameters:
string$elementsthe list of elements (field definitions) in INI format.
    {
        if (!is_string($elements)) {
            throw new InvalidArgumentException(
                "Cannot set elements. Elements must be a string."
            );
        }

        // reset elements.
        $this->_hasValidElements = null;
        $this->_elements         = null;
        $this->_form             = null;

        return $this->_setValue('elements', $elements);
    }
P4Cms_Content_Type::setGroup ( group)

Set a new group.

Parameters:
string | null$groupThe new group to use.
Returns:
P4Cms_Content_Type To maintain a fluent interface.
    {
        if (!is_string($group) && !is_null($group)) {
            throw new InvalidArgumentException("Group must be a string or null.");
        }

        return $this->_setValue('group', $group);
    }
P4Cms_Content_Type::setIcon ( icon)

Set a new icon.

Parameters:
string | null$iconThe new icon to use.
Returns:
P4Cms_Content_Type To maintain a fluent interface.
    {
        if (!is_string($icon) && !is_null($icon)) {
            throw new InvalidArgumentException("Icon must be a string or null.");
        }

        return $this->_setValue('icon', $icon);
    }
P4Cms_Content_Type::setIconFromFile ( file)

Uses one method rather than two to set the icon for a content type.

Parameters:
string$fileThe file to use as an icon
Returns:
P4Cms_Content_Type To maintain a fluent interface.
    {
        $type = P4Cms_Validate_File_MimeType::getTypeOfFile($file);
        $data = file_get_contents($file);

        $this->setIcon($data)
             ->setFieldMetadata('icon', array('mimeType' => $type));

        return $this;
    }
P4Cms_Content_Type::setId ( id)

Set the id of the content type.

May contain alpha-numeric characters, dashes and underscores.

Parameters:
string | null$idthe id of this content type.
Returns:
P4Cms_Content_Type provides fluent interface.

Reimplemented from P4Cms_Record.

    {
        $validator = new P4Cms_Validate_RecordId;
        $validator->setAllowForwardSlash(false);
        if (!$validator->isValid($id)) {
            throw new InvalidArgumentException(
                "Cannot set content-type id. Id contains invalid characters."
            );
        }

        return parent::setId($id);
    }
P4Cms_Content_Type::setLabel ( label)

Set a new label.

Parameters:
string | null$labelThe new label to use.
Returns:
P4Cms_Content_Type To maintain a fluent interface.
    {
        if (!is_string($label) && !is_null($label)) {
            throw new InvalidArgumentException("Label must be a string or null.");
        }

        return $this->_setValue('label', $label);
    }
P4Cms_Content_Type::setLayout ( layout)

Set the layout script to use.

Parameters:
string | null$layoutthe name of the layout to use.
Returns:
P4Cms_Content_Type to maintain a fluent interface.
    {
        if (!is_string($layout) && !is_null($layout)) {
            throw new InvalidArgumentException("Layout must be a string or null.");
        }

        return $this->_setValue('layout', $layout);
    }
P4Cms_Content_Type::validateElements ( )

Validate the element for use in a form and a content type record.

Returns:
array the list of validation errors; an empty list means all elements are valid.
    {
        $this->_validationErrors = array();
        $this->_hasValidElements = true; // assume valid

        // ensure that element names validate as record field names.
        $validator = new P4Cms_Validate_RecordField;
        foreach (array_keys($this->getElements()) as $element) {
            if (!$validator->isValid($element)) {
                $this->_hasValidElements = false;
                $messages = array();
                foreach ($validator->getMessages() as $message) {
                    $messages[] = lcfirst(preg_replace("/\.$/", "", $message));
                }

                $this->_validationErrors[] = "Element '$element' failed validation: ". implode(', ', $messages);
            }
        }

        // ensure that elements can produce a form.
        if ($this->_hasValidElements) {
            try {
                $this->getFormElements();
            } catch (Exception $e) {
                $this->_validationErrors[] = $e->getMessage();
                $this->_validationErrors[] = 'Please check your input and be sure to use only valid element types.';
                $this->_hasValidElements = false;
            }
        }

        // ensure that the form has the same elements as the type
        if ($this->_hasValidElements) {
            if (array_keys($this->getElements()) != array_keys($this->getFormElements())) {
                $this->_validationErrors[] = 'One or more elements are not valid as form elements.';
                $this->_hasValidElements = false;
            }
        }

        return $this->_validationErrors;
    }

Member Data Documentation

P4Cms_Content_Type::$_elements = null [protected]
P4Cms_Content_Type::$_fields [static, protected]
Initial value:
 array(
        'label'         => array(
            'accessor'  => 'getLabel',
            'mutator'   => 'setLabel',
        ),
        'group'         => array(
            'accessor'  => 'getGroup',
            'mutator'   => 'setGroup',
        ),
        'icon'          => array(
            'accessor'  => 'getIcon',
            'mutator'   => 'setIcon',
        ),
        'description'   => array(
            'accessor'  => 'getDescription',
            'mutator'   => 'setDescription',
        ),
        'elements'      => array(
            'accessor'  => 'getElements',
            'mutator'   => 'setElements',
        ),
        'layout'
    )

Specifies the array of fields that the current Record class wishes to use.

The implementing class MUST set this property.

Reimplemented from P4Cms_Record.

P4Cms_Content_Type::$_fileContentField = 'elements' [static, protected]

Specifies the name of the record field which will be persisted in the file used to store the records.

If desired, the implementing class needs to set this property to match an entry defined in the $_fields array. If left null, all fields will persist as file attributes.

Reimplemented from P4Cms_Record.

P4Cms_Content_Type::$_form = null [protected]
P4Cms_Content_Type::$_hasValidElements = null [protected]
P4Cms_Content_Type::$_storageSubPath = 'content-types' [static, protected]

Specifies the sub-path to use for storage of records.

This is used in combination with the records path (provided by the storage adapter) to construct the full storage path. The implementing class MUST set this property.

Reimplemented from P4Cms_Record.

P4Cms_Content_Type::$_validationErrors = array() [protected]

The documentation for this class was generated from the following file: