Location: PHPKode > projects > QuickApps CMS > QuickAppsCMS-QuickApps-CMS-f24654d/app/Model/Behavior/SluggableBehavior.php
<?php
/**
 * Sluggable Behavior class file.
 *
 * @filesource
 * @author Mariano Iglesias
 * @link http://cake-syrup.sourceforge.net/ingredients/sluggable-behavior/
 * @version    $Revision: 36 $
 * @license    http://www.opensource.org/licenses/mit-license.php The MIT License
 * @package app
 * @subpackage app.models.behaviors
 */

/**
 * Model behavior to support generation of slugs for models.
 *
 * @package app
 * @subpackage app.models.behaviors
 */
class SluggableBehavior extends ModelBehavior
{
    /**
     * Contain settings indexed by model name.
     *
     * @var array
     * @access private
     */
    var $__settings = array();

    /**
     * Initiate behavior for the model using specified settings. Available settings:
     *
     * - label:     (array | string, optional) set to the field name that contains the
     *                 string from where to generate the slug, or a set of field names to
     *                 concatenate for generating the slug. DEFAULTS TO: title
     *
     * - slug:        (string, optional) name of the field name that holds generated slugs.
     *                 DEFAULTS TO: slug
     *
     * - separator:    (string, optional) separator character / string to use for replacing
     *                 non alphabetic characters in generated slug. DEFAULTS TO: -
     *
     * - length:    (integer, optional) maximum length the generated slug can have.
     *                 DEFAULTS TO: 200
     *
     * - overwrite: (boolean, optional) set to true if slugs should be re-generated when
     *                 updating an existing record. DEFAULTS TO: true
     *
     * @param object $Model Model using the behaviour
     * @param array $settings Settings to override for model.
     * @access public
     */
    function setup(&$Model, $settings = array())
    {
        $default = array('label' => array('title'), 'slug' => 'slug', 'separator' => '-', 'length' => 200, 'overwrite' => true, 'translation' => null);

        if (!isset($this->__settings[$Model->alias]))
        {
            $this->__settings[$Model->alias] = $default;
        }

        $this->__settings[$Model->alias] = am($this->__settings[$Model->alias], (is_array($settings) ?  $settings : array()));
    }

    /**
     * Run before a model is saved, used to set up slug for model.
     *
     * @param object $Model Model about to be saved.
     * @return boolean true if save should proceed, false otherwise
     * @access public
     */
    function beforeSave(&$Model)
    {
        $return = parent::beforeSave($Model);

        // Make label fields an array

        if (!is_array($this->__settings[$Model->alias]['label']))
        {
            $this->__settings[$Model->alias]['label'] = array($this->__settings[$Model->alias]['label']);
        }

        // Make sure all label fields are available

        foreach ($this->__settings[$Model->alias]['label'] as $field)
        {
            if (!$Model->hasField($field))
            {
                return $return;
            }
        }

        // See if we should be generating a slug
        if ($Model->hasField($this->__settings[$Model->alias]['slug']) && ($this->__settings[$Model->alias]['overwrite'] || empty($Model->id)))
        {
            // Build label out of data in label fields, if available, or using a default slug otherwise

            $label = '';
            foreach ($this->__settings[$Model->alias]['label'] as $field)
            {
                if (!empty($Model->data[$Model->alias][$field]))
                {
                    $label .= (!empty($label) ?  ' ' : '') . $Model->data[$Model->alias][$field];
                }
            }

            // Keep on going only if we've got something to slug

            if (!empty($label))
            {
                // Get the slug

                $slug = $this->__slug($label, $this->__settings[$Model->alias]);

                // Look for slugs that start with the same slug we've just generated
                // Bug 1
                // The following line is not working any more:
                // $conditions = array($Model->alias . '.' . $this->__settings[$Model->alias]['slug'] => 'LIKE ' . $slug . '%');

                // Fix for Bug1:
                //$conditions = array($Model->alias . '.' . $this->__settings[$Model->alias]['slug'] => $slug); // Fix 1
                $conditions = array($Model->alias . '.' . $this->__settings[$Model->alias]['slug'].' LIKE' => $slug.'%'); // Fix 2

                if (!empty($Model->id))
                {
                    // Bug 2
                    // The following line is not working any more:
                    // $conditions[$Model->alias . '.' . $Model->primaryKey] = '!= ' . $Model->id;

                    // Fix for Bug 2:
                    $conditions['not'] = array(
                        $Model->alias . '.' . $Model->primaryKey =>
                            $Model->id
                    );
                }
                $result = $Model->find('all', array('conditions' => $conditions, 'fields' => array($Model->primaryKey, $this->__settings[$Model->alias]['slug']), 'recursive' => -1));
                $sameUrls = null;

                if (!empty($result))
                {
                    $sameUrls = Set::extract($result, '{n}.' . $Model->alias . '.' . $this->__settings[$Model->alias]['slug']);
                }

                // If we have collissions

                if (!empty($sameUrls))
                {
                    $begginingSlug = $slug;
                    $index = 1;

                    // Attach an ending incremental number until we find a free slug

                    while($index > 0)
                    {
                        if (!in_array($begginingSlug . $this->__settings[$Model->alias]['separator'] . $index, $sameUrls))
                        {
                            $slug = $begginingSlug . $this->__settings[$Model->alias]['separator'] . $index;
                            $index = -1;
                        }

                        $index++;
                    }
                }

                // Now set the slug as part of the model data to be saved, making sure that
                // we are on the white list of fields to be saved

                if (!empty($Model->whitelist) && !in_array($this->__settings[$Model->alias]['slug'], $Model->whitelist))
                {
                    $Model->whitelist[] = $this->__settings[$Model->alias]['slug'];
                }

                $Model->data[$Model->alias][$this->__settings[$Model->alias]['slug']] = $slug;
            }
        }

        return $return;
    }

    /**
     * Generate a slug for the given string using specified settings.
     *
     * @param string $string String from where to generate slug
     * @param array $settings Settings to use (looks for 'separator' and 'length')
     * @return string Slug for given string
     * @access private
     */
    function __slug($string, $settings) {
        $string = Inflector::slug($string, $settings['separator']);
        $string = strtolower($string);
        if (strlen($string) > $settings['length'])
            $string = substr($string, 0, $settings['length']);
        return $string;
    }
}
Return current item: QuickApps CMS