From: avl Date: Mon, 18 Aug 2008 13:02:13 +0000 (+0300) Subject: Real ORM Sluggable Action X-Git-Tag: 0.5~529 X-Git-Url: https://git.andy128k.dev/?a=commitdiff_plain;h=e377bb4e42f7bf1ee303dc41cd62b3c61eb2d917;p=ipf.git Real ORM Sluggable Action --- diff --git a/ipf/orm/template/listener/sluggable.php b/ipf/orm/template/listener/sluggable.php new file mode 100644 index 0000000..e416b8c --- /dev/null +++ b/ipf/orm/template/listener/sluggable.php @@ -0,0 +1,113 @@ +_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 index 0000000..6e0e87b --- /dev/null +++ b/ipf/orm/template/sluggable.php @@ -0,0 +1,34 @@ + '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