[Solar-svn] Revision 2773
pmjones at solarphp.com
pmjones at solarphp.com
Sun Sep 23 15:24:13 CDT 2007
branch: Solar_Model_*: major revamp of all content model classes in line with recent Model/Record/Collection classes
Added: branches/orm/Solar/Model/Areas/Collection.php
===================================================================
--- branches/orm/Solar/Model/Areas/Collection.php (rev 0)
+++ branches/orm/Solar/Model/Areas/Collection.php 2007-09-23 20:24:13 UTC (rev 2773)
@@ -0,0 +1,2 @@
+<?php
+class Solar_Model_Areas_Collection extends Solar_Model_Collection {}
\ No newline at end of file
Added: branches/orm/Solar/Model/Areas/Record.php
===================================================================
--- branches/orm/Solar/Model/Areas/Record.php (rev 0)
+++ branches/orm/Solar/Model/Areas/Record.php 2007-09-23 20:24:13 UTC (rev 2773)
@@ -0,0 +1,2 @@
+<?php
+class Solar_Model_Areas_Record extends Solar_Model_Record {}
\ No newline at end of file
Modified: branches/orm/Solar/Model/Areas.php
===================================================================
--- branches/orm/Solar/Model/Areas.php 2007-09-23 20:19:52 UTC (rev 2772)
+++ branches/orm/Solar/Model/Areas.php 2007-09-23 20:24:13 UTC (rev 2773)
@@ -36,7 +36,7 @@
'prefs' => 'clob',
);
- $this->_indexes = array(
+ $this->_index = array(
'created',
'updated',
'name' => 'unique',
Added: branches/orm/Solar/Model/Collection.php
===================================================================
--- branches/orm/Solar/Model/Collection.php (rev 0)
+++ branches/orm/Solar/Model/Collection.php 2007-09-23 20:24:13 UTC (rev 2773)
@@ -0,0 +1,2 @@
+<?php
+class Solar_Model_Collection extends Solar_Sql_Model_Collection {}
\ No newline at end of file
Modified: branches/orm/Solar/Model/Nodes/Bookmarks/Locale/en_US.php
===================================================================
--- branches/orm/Solar/Model/Nodes/Bookmarks/Locale/en_US.php 2007-09-23 20:19:52 UTC (rev 2772)
+++ branches/orm/Solar/Model/Nodes/Bookmarks/Locale/en_US.php 2007-09-23 20:24:13 UTC (rev 2773)
@@ -1,7 +1,8 @@
<?php
return array(
- 'LABEL_URI' => 'Location',
- 'LABEL_SUBJ' => 'Title',
- 'LABEL_SUMM' => 'Description',
- 'LABEL_POS' => 'Rank',
+ 'LABEL_URI' => 'Location',
+ 'LABEL_SUBJ' => 'Title',
+ 'LABEL_SUMM' => 'Description',
+ 'LABEL_POS' => 'Rank',
+ 'LABEL_TAGS_AS_STRING' => 'Tags',
);
\ No newline at end of file
Modified: branches/orm/Solar/Model/Nodes/Bookmarks/Record.php
===================================================================
--- branches/orm/Solar/Model/Nodes/Bookmarks/Record.php 2007-09-23 20:19:52 UTC (rev 2772)
+++ branches/orm/Solar/Model/Nodes/Bookmarks/Record.php 2007-09-23 20:24:13 UTC (rev 2773)
@@ -21,12 +21,19 @@
'cols' => 48,
),
),
+ 'tags_as_string' => array(
+ 'type' => 'text',
+ 'attribs' => array(
+ 'size' => 48,
+ ),
+ ),
'pos' => array(
'attribs' => array(
'size' => 3,
),
),
);
+
return parent::form($cols);
}
}
\ No newline at end of file
Modified: branches/orm/Solar/Model/Nodes/Bookmarks.php
===================================================================
--- branches/orm/Solar/Model/Nodes/Bookmarks.php 2007-09-23 20:19:52 UTC (rev 2772)
+++ branches/orm/Solar/Model/Nodes/Bookmarks.php 2007-09-23 20:24:13 UTC (rev 2773)
@@ -4,5 +4,6 @@
{
parent::_setup();
$this->_addFilter('uri', 'validateNotBlank');
+ $this->_addFilter('tags_as_string', 'validateNotBlank');
}
}
Modified: branches/orm/Solar/Model/Nodes/Record.php
===================================================================
--- branches/orm/Solar/Model/Nodes/Record.php 2007-09-23 20:19:52 UTC (rev 2772)
+++ branches/orm/Solar/Model/Nodes/Record.php 2007-09-23 20:24:13 UTC (rev 2773)
@@ -1,2 +1,130 @@
<?php
-class Solar_Model_Nodes_Record extends Solar_Model_Record {}
\ No newline at end of file
+class Solar_Model_Nodes_Record extends Solar_Model_Record {
+
+ public function __getTagsAsString()
+ {
+ // if exactly null, populate for the first time.
+ if ($this->_data['tags_as_string'] === null) {
+ $text = '';
+ foreach ($this->tags as $tag) {
+ $text .= "{$tag->name} ";
+ }
+ $this->_data['tags_as_string'] = rtrim($text);
+ }
+
+ return $this->_data['tags_as_string'];
+ }
+
+ public function __setTagsAsString($val)
+ {
+ $val = preg_replace('/[ ]{2,}/', ' ', $val);
+ $this->_data['tags_as_string'] = trim($val);
+ $new = explode(' ', $this->_data['tags_as_string']);
+ $new = array_unique($new);
+
+ // build a new tag collection
+ $model = $this->tags->getModel();
+ $coll = $model->newCollection();
+ foreach ($new as $name) {
+ $record = $model->fetchNew();
+ $record->name = $name;
+ $coll[] = $record;
+ }
+
+ // reset the tags collection
+ $this->tags = $coll;
+ }
+
+ // work with related values before they get saved.
+ // relateds: areas, nodes, taggings, tags
+ public function _postSave()
+ {
+ // -------------------------------------------------------------
+ //
+ // make sure that each tag actually exists; insert a new tag
+ // record for each new one.
+ //
+
+ // hold on to the tags model
+ $tags_model = $this->tags->getModel();
+
+ // get the list of tags on the record
+ $tag_names = $this->tags->getNames();
+ if ($tag_names) {
+ // make sure each tag actually exists as a record. tag names
+ // that do not exist will not be in this array.
+ $params = array(
+ 'where' => array(
+ 'tags.name IN (?)' => $tag_names,
+ ),
+ );
+ $existing_tags = $tags_model->fetchAll($params);
+ } else {
+ $existing_tags = $tags_model->newCollection(null);
+ }
+
+ // loop through the tags
+ foreach ($this->tags as $key => $tag) {
+
+ // does this tag already exist?
+ foreach ($existing_tags as $existing) {
+ if ($tag->name == $existing->name) {
+ // replace with the existing tag record.
+ // this lets us "connect" user-entered tag names
+ // with existing records. capture both the tag from
+ // the loop and reset the collection value.
+ $tag = $existing;
+ $this->tags[$key] = $existing;
+ break;
+ }
+ }
+
+ // if status is still 'new' then save it
+ if ($tag->getStatus() == 'new') {
+ $tag->save();
+ }
+
+ // look for a tagging on this tag
+ $found = false;
+ foreach ($this->taggings as $tagging) {
+ // must match node ID and tag ID
+ $match = $tagging->node_id == $this->id &&
+ $tagging->tag_id == $tag->id;
+ if ($match) {
+ $found = true;
+ break;
+ }
+ }
+
+ // did we find a tagging for the tag?
+ if (! $found) {
+ // no, create one ...
+ $tagging = $this->taggings->getModel()->fetchNew();
+ $tagging->node_id = $this->id;
+ $tagging->tag_id = $tag->id;
+
+ // ... and add to the collection
+ $this->taggings[] = $tagging;
+ }
+ }
+
+ // remove taggings that don't exist any more
+ foreach ($this->taggings as $key => $tagging) {
+ $found = false;
+ foreach ($this->tags as $tag) {
+ $match = $tagging->node_id == $this->id &&
+ $tagging->tag_id == $tag->id;
+ if ($match) {
+ $found = true;
+ break;
+ }
+ }
+
+ // does the tagging match a tag?
+ if (! $found) {
+ // no, remove from the taggings
+ $tagging->delete();
+ }
+ }
+ }
+}
\ No newline at end of file
Modified: branches/orm/Solar/Model/Nodes.php
===================================================================
--- branches/orm/Solar/Model/Nodes.php 2007-09-23 20:19:52 UTC (rev 2772)
+++ branches/orm/Solar/Model/Nodes.php 2007-09-23 20:24:13 UTC (rev 2773)
@@ -82,7 +82,7 @@
'prefs' => 'clob',
);
- $this->_indexes = array(
+ $this->_index = array(
'created',
'updated',
'area_id',
@@ -103,6 +103,7 @@
* Special columns
*/
$this->_serialize_cols[] = 'prefs';
+ $this->_calculate_cols[] = 'tags_as_string';
/**
* Filters
@@ -122,6 +123,7 @@
$this->_addFilter('editor_ipaddr', 'validateIpv4');
$this->_addFilter('locale', 'validateLocaleCode');
$this->_addFilter('mime', 'validateMimeType');
+ $this->_addFilter('tags_as_string', 'validateSepWords');
/**
* Relationships.
@@ -143,5 +145,94 @@
'through_key' => 'tag_id',
));
}
+
+ public function fetchAllByTags($tag_list, $params = null)
+ {
+ // no tags? fetch all to pre-empt errors related to "IN()" not
+ // having a list to work with.
+ $tag_list = $this->_fixTagList($tag_list);
+ if (! $tag_list) {
+ return $this->fetchAll($params);
+ }
+
+ // fetch
+ $select = $this->_newSelectByTags($tag_list, $params);
+ return $this->_fetchAll($select, $params);
+ }
+
+ protected function _fixTagList($tag_list)
+ {
+ // convert to array
+ if (! is_array($tag_list)) {
+ $tag_list = preg_split('/\s+/', trim((string) $tag_list));
+ }
+
+ // no duplicates allowed
+ $tag_list = array_unique($tag_list);
+
+ // if the string tag-list is empty, the preg-split leaves one empty
+ // element in the array.
+ if ($tag_list[0] == '') {
+ $tag_list = array();
+ }
+
+ // done!
+ return $tag_list;
+ }
+
+ protected function _newSelectByTags($tag_list, $params)
+ {
+ // setup
+ $params = $this->_fixSelectParams($params);
+ $select = $this->newSelect($params['eager']);
+
+ // catalog entries for joining
+ $taggings = $this->_related['taggings'];
+ $tags = $this->_related['tags'];
+
+ // primary key on the nodes table as an alias; e.g., "nodes.id"
+ $native_primary = "{$this->_model_name}.{$this->_primary_col}";
+
+ // http://forge.mysql.com/wiki/TagSchema
+ // build the select differently from other fetchAll() statements
+ $select->distinct($params['distinct'])
+ ->from("{$this->_table_name} AS {$this->_model_name}", $params['cols'])
+ // join taggings on nodes
+ ->join(
+ "{$taggings['foreign_table']} AS {$taggings['foreign_alias']}",
+ "{$taggings['foreign_alias']}.node_id = $native_primary"
+ )
+ // join tags on taggings
+ ->join(
+ "{$tags['foreign_table']} AS {$tags['foreign_alias']}",
+ "{$tags['foreign_alias']}.id = {$taggings['foreign_alias']}.tag_id"
+ )
+ // select for the listed tags
+ ->where("{$tags['foreign_alias']}.name IN (?)", $tag_list)
+ // user-provided WHERE
+ ->multiWhere($params['where'])
+ // group by nodes.id to collapse multiple nodes (1 for each tag)
+ ->group($native_primary)
+ // make sure the tag-count matches
+ ->having("COUNT($native_primary) = ?", count($tag_list))
+ // user-provided ORDER, paging, etc
+ ->order($params['order'])
+ ->setPaging($params['paging'])
+ ->limitPage($params['page'])
+ ->bind($params['bind']);
+
+ // done!
+ return $select;
+ }
+
+ public function countPagesByTags($tag_list, $params = null)
+ {
+ $tag_list = $this->_fixTagList($tag_list);
+ if (! $tag_list) {
+ return $this->countPages($params);
+ }
+
+ $select = $this->_newSelectByTags($tag_list, $params);
+ return $select->countPages('bookmarks.id');
+ }
}
-
Added: branches/orm/Solar/Model/Tags/Collection.php
===================================================================
--- branches/orm/Solar/Model/Tags/Collection.php (rev 0)
+++ branches/orm/Solar/Model/Tags/Collection.php 2007-09-23 20:24:13 UTC (rev 2773)
@@ -0,0 +1,12 @@
+<?php
+class Solar_Model_Tags_Collection extends Solar_Model_Collection {
+
+ public function getNames()
+ {
+ $list = array();
+ foreach ($this as $tag) {
+ $list[] = $tag->name;
+ }
+ return $list;
+ }
+}
\ No newline at end of file
Added: branches/orm/Solar/Model/Tags/Record.php
===================================================================
--- branches/orm/Solar/Model/Tags/Record.php (rev 0)
+++ branches/orm/Solar/Model/Tags/Record.php 2007-09-23 20:24:13 UTC (rev 2773)
@@ -0,0 +1,2 @@
+<?php
+class Solar_Model_Tags_Record extends Solar_Model_Record {}
\ No newline at end of file
Modified: branches/orm/Solar/Model/Tags.php
===================================================================
--- branches/orm/Solar/Model/Tags.php 2007-09-23 20:19:52 UTC (rev 2772)
+++ branches/orm/Solar/Model/Tags.php 2007-09-23 20:24:13 UTC (rev 2773)
@@ -25,7 +25,7 @@
),
);
- $this->_indexes = array(
+ $this->_index = array(
'name' => 'unique',
);
@@ -47,4 +47,102 @@
'through' => 'taggings',
));
}
+
+ public function fetchAllWithCount($params)
+ {
+ $select = $this->_newSelectWithCount($params);
+ return $this->_fetchAll($select, $params);
+ }
+
+ public function fetchAllByOwnerHandle($owner_handle, $params = null)
+ {
+ $owner_handle = trim($owner_handle);
+ if (! $owner_handle) {
+ return $this->fetchAll($params);
+ }
+
+ // setup
+ $params = $this->_fixSelectParams($params);
+ $select = $this->newSelect($params['eager']);
+
+ // catalog entries for joining
+ $taggings = $this->_related['taggings'];
+ $nodes = $this->_related['nodes'];
+
+ // primary key on this table alias; e.g., tags.id
+ $native_primary = "{$this->_model_name}.{$this->_primary_col}";
+
+ // add a tag-count column
+ $params['cols'][] = "COUNT($native_primary) AS count";
+
+ // build the select
+ $select->distinct($params['distinct'])
+ ->from("{$this->_table_name} AS {$this->_model_name}", $params['cols'])
+ // join taggings on tags
+ ->join(
+ "{$taggings['foreign_table']} AS {$taggings['foreign_alias']}",
+ "{$taggings['foreign_alias']}.tag_id = $native_primary"
+ )
+ // join nodes on taggings
+ ->join(
+ "{$nodes['foreign_table']} AS {$nodes['foreign_alias']}",
+ "{$nodes['foreign_alias']}.id = {$taggings['foreign_alias']}.node_id"
+ )
+ // select for the owner_handle
+ ->where("{$nodes['foreign_alias']}.owner_handle = ?", $owner_handle)
+ // group on primary key for counts
+ ->group($native_primary)
+ // user-provided ORDER, paging, etc
+ ->multiWhere($params['where'])
+ ->order($params['order'])
+ ->setPaging($params['paging'])
+ ->limitPage($params['page'])
+ ->bind($params['bind']);
+
+ // fetch
+ $select = $this->_newSelectWithCount($params);
+ $select->where('nodes.owner_handle = ?', $owner_handle);
+ return $this->_fetchAll($select, $params);
+ }
+
+ protected function _newSelectWithCount($params)
+ {
+ // setup
+ $params = $this->_fixSelectParams($params);
+ $select = $this->newSelect($params['eager']);
+
+ // catalog entries for joining
+ $taggings = $this->_related['taggings'];
+ $nodes = $this->_related['nodes'];
+
+ // primary key on this table alias; e.g., tags.id
+ $native_primary = "{$this->_model_name}.{$this->_primary_col}";
+
+ // add a tag-count column
+ $params['cols'][] = "COUNT($native_primary) AS count";
+
+ // build the select
+ $select->distinct($params['distinct'])
+ ->from("{$this->_table_name} AS {$this->_model_name}", $params['cols'])
+ // join taggings on tags
+ ->join(
+ "{$taggings['foreign_table']} AS {$taggings['foreign_alias']}",
+ "{$taggings['foreign_alias']}.tag_id = $native_primary"
+ )
+ // join nodes on taggings
+ ->join(
+ "{$nodes['foreign_table']} AS {$nodes['foreign_alias']}",
+ "{$nodes['foreign_alias']}.id = {$taggings['foreign_alias']}.node_id"
+ )
+ // group on primary key for counts
+ ->group($native_primary)
+ // user-provided ORDER, paging, etc
+ ->multiWhere($params['where'])
+ ->order($params['order'])
+ ->setPaging($params['paging'])
+ ->limitPage($params['page'])
+ ->bind($params['bind']);
+
+ return $select;
+ }
}
More information about the Solar-svn
mailing list