]> git.andy128k.dev Git - ipf.git/commitdiff
Real ORM Sluggable Action
authoravl <alex.litovchenko@gmail.com>
Mon, 18 Aug 2008 13:02:13 +0000 (16:02 +0300)
committeravl <alex.litovchenko@gmail.com>
Mon, 18 Aug 2008 13:02:13 +0000 (16:02 +0300)
ipf/orm/template/listener/sluggable.php [new file with mode: 0644]
ipf/orm/template/sluggable.php [new file with mode: 0644]

diff --git a/ipf/orm/template/listener/sluggable.php b/ipf/orm/template/listener/sluggable.php
new file mode 100644 (file)
index 0000000..e416b8c
--- /dev/null
@@ -0,0 +1,113 @@
+<?php
+
+class IPF_ORM_Template_Listener_Sluggable extends IPF_ORM_Record_Listener
+{
+    protected $_options = array();
+
+    public function __construct(array $options)
+    {
+        $this->_options = $options;
+    }
+
+    public function preInsert(IPF_ORM_Event $event)
+    {
+        $name = $this->_options['name'];
+
+        $record = $event->getInvoker();
+
+        if ( ! $record->$name) {
+            $record->$name = $this->buildSlug($record);
+        }
+    }
+
+    public function preUpdate(IPF_ORM_Event $event)
+    {
+        if (false !== $this->_options['unique']) {
+            $name = $this->_options['name'];
+    
+            $record = $event->getInvoker();
+
+            if ( ! $record->$name ||
+            (false !== $this->_options['canUpdate'] &&
+            array_key_exists($name, $record->getModified()))) {
+                $record->$name = $this->buildSlug($record);
+            }
+        }
+    }
+
+    protected function buildSlug($record)
+    {
+        if (empty($this->_options['fields'])) {
+            if (method_exists($record, 'getUniqueSlug')) {
+                $value = $record->getUniqueSlug($record);
+            } else {
+                $value = (string) $record;
+            }
+        } else {
+            if ($this->_options['unique'] === true) {   
+                $value = $this->getUniqueSlug($record);
+            } else {  
+                $value = '';
+                foreach ($this->_options['fields'] as $field) {
+                    $value .= $record->$field . ' ';
+                } 
+            }
+        }
+
+        $value =  call_user_func_array($this->_options['builder'], array($value, $record));
+
+        return $value;
+    }
+
+    public function getUniqueSlug($record)
+    {
+        $name = $this->_options['name'];
+        $slugFromFields = '';
+        foreach ($this->_options['fields'] as $field) {
+            $slugFromFields .= $record->$field . ' ';
+        }
+
+        $proposal = $record->$name ? $record->$name : $slugFromFields;
+        $proposal =  call_user_func_array($this->_options['builder'], array($proposal, $record));
+        $slug = $proposal;
+
+        $whereString = 'r.' . $name . ' LIKE ?';
+        $whereParams = array($proposal.'%');
+        
+        if ($record->exists()) {
+            $identifier = $record->identifier();
+            $whereString .= ' AND r.' . implode(' != ? AND r.', $record->getTable()->getIdentifierColumnNames()) . ' != ?';
+            $whereParams = array_merge($whereParams, array_values($identifier));
+        }
+
+        foreach ($this->_options['uniqueBy'] as $uniqueBy) {
+            if (is_null($record->$uniqueBy)) {
+                $whereString .= ' AND r.'.$uniqueBy.' IS NULL';
+            } else {
+                $whereString .= ' AND r.'.$uniqueBy.' = ?';
+                $whereParams[] =  $record->$uniqueBy;
+            }
+        }
+
+        $query = IPF_ORM_Query::create()
+        ->select('r.'.$name)
+        ->from(get_class($record).' r')
+        ->where($whereString , $whereParams)
+        ->setHydrationMode(IPF_ORM::HYDRATE_ARRAY);
+
+        $similarSlugResult = $query->execute();
+
+        $similarSlugs = array();
+        foreach ($similarSlugResult as $key => $value) {
+            $similarSlugs[$key] = $value[$name];
+        }
+
+        $i = 1;
+        while (in_array($slug, $similarSlugs)) {
+            $slug = $proposal.'-'.$i;
+            $i++;
+        }
+
+        return  $slug;
+    }
+}
\ No newline at end of file
diff --git a/ipf/orm/template/sluggable.php b/ipf/orm/template/sluggable.php
new file mode 100644 (file)
index 0000000..6e0e87b
--- /dev/null
@@ -0,0 +1,34 @@
+<?php
+
+class IPF_ORM_Template_Sluggable extends IPF_ORM_Template{
+    protected $_options = array('name'          =>  'slug',
+                                'type'          =>  'string',
+                                'length'        =>  255,
+                                'unique'        =>  true,
+                                'options'       =>  array(),
+                                'fields'        =>  array(),
+                                'uniqueBy'      =>  array(),
+                                'uniqueIndex'   =>  true,
+                                'canUpdate'     =>  false,
+                                'builder'       =>  array('IPF_ORM_Inflector', 'urlize'),
+                                'indexName'     =>  'sluggable'
+    );
+
+    public function __construct(array $options = array())
+    {
+        $this->_options = IPF_ORM_Utils::arrayDeepMerge($this->_options, $options);
+    }
+
+    public function setTableDefinition()
+    {
+        $this->hasColumn($this->_options['name'], $this->_options['type'], $this->_options['length'], $this->_options['options']);
+        
+        if ($this->_options['unique'] == true && $this->_options['uniqueIndex'] == true && ! empty($this->_options['fields'])) {
+            $indexFields = array($this->_options['name']);
+            $indexFields = array_merge($indexFields, $this->_options['uniqueBy']);
+            $this->index($this->_options['indexName'], array('fields' => $indexFields,
+                                                             'type' => 'unique'));
+        }
+        $this->addListener(new IPF_ORM_Template_Listener_Sluggable($this->_options));
+    }
+}
\ No newline at end of file