PageRenderTime 25ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/behavior/TaggableBehavior.php

https://github.com/mmonguilod/sfPropel15TaggableBehaviorPlugin
PHP | 304 lines | 223 code | 42 blank | 39 comment | 20 complexity | 40665c2e7a2ff09924305e8e11ae02e8 MD5 | raw file
  1. <?php
  2. /*
  3. * matteosister <matteog@gmail.com>
  4. * Just for fun...
  5. */
  6. class TaggableBehavior extends Behavior {
  7. protected $parameters = array(
  8. 'tagging_table' => '%TABLE%_tagging',
  9. 'tagging_table_phpname' => '%PHPNAME%Tagging',
  10. 'tag_table' => 'taggable_tag',
  11. 'tag_table_phpname' => 'Tag',
  12. );
  13. protected $taggingTable,
  14. $tagTable,
  15. $objectBuilderModifier,
  16. $queryBuilderModifier,
  17. $peerBuilderModifier;
  18. public function modifyDatabase()
  19. {
  20. die('mod db');
  21. }
  22. public function modifyTable()
  23. {
  24. $this->createTagTable();
  25. $this->createTaggingTable();
  26. }
  27. protected function createTagTable()
  28. {
  29. $table = $this->getTable();
  30. $database = $table->getDatabase();
  31. $tagTableName = $this->getTagTableName();
  32. $tagTablePhpName = $this->replaceTokens($this->parameters['tag_table_phpname']);
  33. if($database->hasTable($tagTableName)) {
  34. $this->tagTable = $database->getTable($tagTableName);
  35. } else {
  36. $this->tagTable = $database->addTable(array(
  37. 'name' => $tagTableName,
  38. 'phpName' => $tagTablePhpName,
  39. 'package' => $table->getPackage(),
  40. 'schema' => $table->getSchema(),
  41. 'namespace' => $table->getNamespace(),
  42. ));
  43. // every behavior adding a table should re-execute database behaviors
  44. // see bug 2188 http://www.propelorm.org/changeset/2188
  45. foreach ($database->getBehaviors() as $behavior) {
  46. $behavior->modifyDatabase();
  47. }
  48. }
  49. if (!$this->tagTable->hasColumn('id')) {
  50. $this->tagTable->addColumn(array(
  51. 'name' => 'id',
  52. 'type' => PropelTypes::INTEGER,
  53. 'primaryKey' => 'true',
  54. 'autoIncrement' => 'true',
  55. ));
  56. }
  57. if (!$this->tagTable->hasColumn('name')) {
  58. $this->tagTable->addColumn(array(
  59. 'name' => 'name',
  60. 'type' => PropelTypes::VARCHAR,
  61. 'size' => '60',
  62. 'primaryString' => 'true'
  63. ));
  64. }
  65. }
  66. protected function createTaggingTable()
  67. {
  68. $table = $this->getTable();
  69. $database = $table->getDatabase();
  70. $pks = $this->getTable()->getPrimaryKey();
  71. if (count($pks) > 1) {
  72. throw new EngineException('The Taggable behavior does not support tables with composite primary keys');
  73. }
  74. $taggingTableName = $this->getTaggingTableName();
  75. if($database->hasTable($taggingTableName)) {
  76. $this->taggingTable = $database->getTable($taggingTableName);
  77. } else {
  78. $this->taggingTable = $database->addTable(array(
  79. 'name' => $taggingTableName,
  80. 'phpName' => $this->replaceTokens($this->parameters['tagging_table_phpname']),
  81. 'package' => $table->getPackage(),
  82. 'schema' => $table->getSchema(),
  83. 'namespace' => $table->getNamespace(),
  84. ));
  85. // every behavior adding a table should re-execute database behaviors
  86. // see bug 2188 http://www.propelorm.org/changeset/2188
  87. foreach ($database->getBehaviors() as $behavior) {
  88. $behavior->modifyDatabase();
  89. }
  90. }
  91. $objFkColumn;
  92. if ($this->taggingTable->hasColumn($table->getName().'_id')) {
  93. $objFkColumn = $this->taggingTable->getColumn($table->getName().'_id');
  94. } else {
  95. $objFkColumn = $this->taggingTable->addColumn(array(
  96. 'name' => $table->getName().'_id',
  97. 'type' => PropelTypes::INTEGER,
  98. 'primaryKey' => 'true'
  99. ));
  100. }
  101. $tagFkColumn;
  102. if ($this->taggingTable->hasColumn('tag_id')) {
  103. $tagFkColumn = $this->taggingTable->getColumn('tag_id');
  104. } else {
  105. $tagFkColumn = $this->taggingTable->addColumn(array(
  106. 'name' => 'tag_id',
  107. 'type' => PropelTypes::INTEGER,
  108. 'primaryKey' => 'true'
  109. ));
  110. }
  111. $this->taggingTable->setIsCrossRef(true);
  112. $fkTag = new ForeignKey();
  113. $fkTag->setForeignTableCommonName($this->tagTable->getName());
  114. $fkTag->setForeignSchemaName($this->tagTable->getSchema());
  115. $fkTag->setOnDelete(ForeignKey::CASCADE);
  116. $fkTag->setOnUpdate(ForeignKey::NONE);
  117. foreach ($pks as $column) {
  118. $fkTag->addReference($tagFkColumn, $column->getName());
  119. }
  120. $this->taggingTable->addForeignKey($fkTag);
  121. $fkObj = new ForeignKey();
  122. $fkObj->setForeignTableCommonName($this->getTable()->getName());
  123. $fkObj->setForeignSchemaName($this->getTable()->getSchema());
  124. $fkObj->setOnDelete(ForeignKey::CASCADE);
  125. $fkObj->setOnUpdate(ForeignKey::NONE);
  126. foreach ($pks as $column) {
  127. $fkObj->addReference($objFkColumn, $column->getName());
  128. }
  129. $this->taggingTable->addForeignKey($fkObj);
  130. }
  131. /**
  132. * Adds methods to the object
  133. */
  134. public function objectMethods($builder)
  135. {
  136. $this->builder = $builder;
  137. $script = '';
  138. $this->addAddTagsMethod($script);
  139. $this->addRemoveTagMethod($script);
  140. return $script;
  141. }
  142. private function addAddTagsMethod(&$script)
  143. {
  144. $table = $this->getTable();
  145. $script .= "
  146. /**
  147. * Add tags
  148. * @param array|string \$tags A string for a single tag or an array of strings for multiple tags
  149. * @param PropelPDO \$con optional connection object
  150. */
  151. public function addTags(\$tags, PropelPDO \$con = null) {
  152. \$arrTags = is_string(\$tags) ? explode(',', \$tags) : \$tags;
  153. // Remove duplicate tags.
  154. \$arrTags = array_intersect_key(\$arrTags, array_unique(array_map('strtolower', \$arrTags)));
  155. foreach (\$arrTags as \$tag) {
  156. \$tag = trim(\$tag);
  157. if (\$tag == \"\") return;
  158. \$theTag = {$this->tagTable->getPhpName()}Query::create()->filterByName(\$tag)->findOne(\$con);
  159. // if the tag do not already exists
  160. if (null === \$theTag) {
  161. // create the tag
  162. \$theTag = new {$this->tagTable->getPhpName()}();
  163. \$theTag->setName(\$tag);
  164. \$theTag->save(\$con);
  165. }
  166. // Add the tag **only** if not already associated
  167. \$found = false;
  168. \$coll = \$this->getTags(null, \$con);
  169. foreach (\$coll as \$t) {
  170. if (\$t->getId() == \$theTag->getId()) {
  171. \$found = true;
  172. break;
  173. }
  174. }
  175. if (!\$found) {
  176. \$this->addTag(\$theTag);
  177. }
  178. }
  179. }
  180. /**
  181. * Remove all tags
  182. * @param PropelPDO \$con optional connection object
  183. */
  184. public function removeAllTags(PropelPDO \$con = null) {
  185. // Get all tags for this object
  186. \$taggings = \$this->get{$this->taggingTable->getPhpName()}s(\$con);
  187. foreach (\$taggings as \$tag) {
  188. \$tag->delete(\$con);
  189. }
  190. }
  191. ";
  192. }
  193. private function addRemoveTagMethod(&$script)
  194. {
  195. $table = new Table();
  196. $table = $this->getTable();
  197. $script .= "
  198. /**
  199. * Remove a tag
  200. * @param array|string \$tags A string for a single tag or an array of strings for multiple tags
  201. */
  202. public function removeTags(\$tags) {
  203. \$arrTags = is_string(\$tags) ? explode(',', \$tags) : \$tags;
  204. foreach (\$arrTags as \$tag) {
  205. \$tag = trim(\$tag);
  206. \$tagObj = {$this->tagTable->getPhpName()}Query::create()->findOneByName(\$tag);
  207. if (null === \$tagObj) {
  208. return;
  209. }
  210. \$taggings = \$this->get{$this->taggingTable->getPhpName()}s();
  211. foreach (\$taggings as \$tagging) {
  212. if (\$tagging->get{$this->tagTable->getPhpName()}Id() == \$tagObj->getId()) {
  213. \$tagging->delete();
  214. }
  215. }
  216. }
  217. }
  218. ";
  219. }
  220. /**
  221. * Adds method to the query object
  222. */
  223. public function queryMethods($builder)
  224. {
  225. $this->builder = $builder;
  226. $script = '';
  227. $this->addFilterByTagName($script);
  228. return $script;
  229. }
  230. protected function addFilterByTagName(&$script)
  231. {
  232. $script .= "
  233. /**
  234. * Filter the query on the tag name
  235. *
  236. * @param string \$tagName A single tag name
  237. *
  238. * @return " . $this->builder->getStubQueryBuilder()->getClassname() . " The current query, for fluid interface
  239. */
  240. public function filterByTagName(\$tagName)
  241. {
  242. return \$this->use".$this->taggingTable->getPhpName()."Query()->useTagQuery()->filterByName(\$tagName)->endUse()->endUse();
  243. }
  244. ";
  245. }
  246. protected function getTagTableName()
  247. {
  248. return $this->replaceTokens($this->getParameter('tag_table'));
  249. }
  250. protected function getTaggingTableName()
  251. {
  252. return $this->replaceTokens($this->getParameter('tagging_table'));
  253. }
  254. public function replaceTokens($string)
  255. {
  256. $table = $this->getTable();
  257. return strtr($string, array(
  258. '%TABLE%' => $table->getName(),
  259. '%PHPNAME%' => $table->getPhpName(),
  260. ));
  261. }
  262. }