diff --git a/README.md b/README.md index d6c513d..1e69fe9 100644 --- a/README.md +++ b/README.md @@ -81,16 +81,18 @@ Terms may be nested, e.g. a "Mammal" term may have children "Dog" and "Cat". ## Known Problems +There are a couple known "warts" due to the manager's use of Ext JS. + **If you right-click on the web context, the menu displays the option to "Create Term Here"** Ideally, the menu shouldn't print this as an option, but the GUI used in the MODX resource tree is not easily -customizable (!@%$#!@ you Ext JS!). So although that option appears in the menu, you are never allowed to complete +customizable. So although that option _appears_ in the menu, you are never _allowed_ to complete that action: Terms must be the children of Taxonomies or other Terms. Some changes to the Ext JS in the core are required before this can be fully fixed. **The GUI issues no warning when you drag a Term into a regular folder** -Although the GUI appears to let you do this, the action is terminated on the backend. Remember: A Term *must* be +Although the GUI _appears_ to let you do this, the action request is terminated on the backend. Remember: A Term *must* be a child of Taxonomy OR of another Term. It may appear that the page has been relocated, but the record will not be saved in the database. Once the MODX manager is reloaded, the page will appear to revert back to its original position. @@ -101,7 +103,7 @@ position. Everett Griffiths -Copyright 2014 +Copyright 2015 Official Documentation: https://github.com/craftsmancoding/taxonomies/wiki diff --git a/composer.json b/composer.json index 0083df7..9386514 100644 --- a/composer.json +++ b/composer.json @@ -39,12 +39,12 @@ "extra": { "package_name": "Taxonomies", "namespace": "taxonomies", - "version": "1.2.1", + "version": "1.3.2", "release": "pl", "category":"Taxonomies", "core_path": "", "orm_path": "model/", - "omit": ["assets/","screenshots/","tests/","composer.json","composer.lock","builds/","phpunit.xml",".git"], + "omit": ["assets/","screenshots/","tests/","composer.json","composer.lock","builds/","phpunit.xml",".git",".gitignore","vendor/craftsmancoding/formbuilder/.gitignore"], "assets_path" : "assets/", "seeds_path": ["model/seeds/base"], "packages":[ diff --git a/docs/changelog.txt b/docs/changelog.txt index b06eec8..1e71fff 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -23,3 +23,17 @@ Limitations: the feature set is somewhat utilitarian: 1.2.1 --------------------------- - Custom icons added + +1.3.0 +--------------------------- +- Fixed hard-coded modx_site_content table name +- Added new parameters to snippets. + +1.3.1 +--------------------------- +- Fixed one more hard-coded modx_site_content table name +- Updated Snippet DocBlocks for compatibility with updated Repoman property parsing. + +1.3.2 +--------------------------- +- Updated package so .gitignore's would not be included. \ No newline at end of file diff --git a/elements/snippets/getPageTerms.php b/elements/snippets/getPageTerms.php index 0c819b1..3e42700 100644 --- a/elements/snippets/getPageTerms.php +++ b/elements/snippets/getPageTerms.php @@ -13,11 +13,11 @@ * * Parameters * ----------------------------- - * @param string $outerTpl Format the Outer Wrapper of List (Optional) - * @param string $innerTpl Format the Inner Item of List - * @param int $page_id get terms for this specific page - * @param int $taxonomy_id limit terms to only this taxonomy - * @param int $limit Limit the result, default to 10 : setting it to 0 will show all + * @param textfield $outerTpl Format the Outer Wrapper of List (Optional) + * @param textfield $innerTpl Format the Inner Item of List + * @param numberfield $page_id get terms for this specific page + * @param textfield $taxonomy_id limit terms to only this taxonomy + * @param numberfield $limit Limit the result, default to 10 : setting it to 0 will show all * * Variables * --------- @@ -47,9 +47,10 @@ $and_where = (is_null($taxonomy_id)) ? '' : 'AND doc.parent = ' . $taxonomy_id; $page_id = (is_null($page_id)) ? $modx->resource->get('id') : $page_id; +$content_table = $modx->getTableName('modResource'); $sql = "SELECT terms.term_id,doc.pagetitle FROM tax_page_terms terms - LEFT JOIN modx_site_content doc ON doc.id = terms.term_id + LEFT JOIN $content_table doc ON doc.id = terms.term_id WHERE terms.page_id = {$page_id} {$and_where} ORDER BY terms.term_id ASC {$limit};"; $obj = $modx->query($sql); diff --git a/elements/snippets/getPagesByTerm.php b/elements/snippets/getPagesByTerm.php index 757bbce..55a0e55 100644 --- a/elements/snippets/getPagesByTerm.php +++ b/elements/snippets/getPagesByTerm.php @@ -9,14 +9,16 @@ * * Parameters * ----------------------------- - * @param string $outerTpl Format the Outer Wrapper of List (Optional) - * @param string $innerTpl Format the Inner Item of List - * @param int $term_id (optional: defaults to the current page id) - * @param bool $exact_matches if true, implied hierarchies are ignored and only pages assigned specifically to term_id will be returned. Default: false - * @param string $classname Set this if you have created a custom join table used to associate taxonomy terms with something other than pages. (optional: default PageTerm) - * @param boolean $debug (optional: if set, will output SQL query for debugging) - * - * @param int $limit Limit the result + * @param textfield $outerTpl Format the Outer Wrapper of List (Optional) + * @param textfield $innerTpl Format the Inner Item of List + * @param numberfield $term_id (optional: defaults to the current page id) + * @param combo-boolean $exact_matches if true, implied hierarchies are ignored and only pages assigned specifically to term_id will be returned. default=false + * @param textfield $classname Set this if you have created a custom join table used to associate taxonomy terms with something other than pages. default=PageTerm + * @param textfield $graph passed to getCollectionGraph, this controls the table joins. Use this only if you need to query your own custom tables. Default={"Page":{}} + * @param textfield $sort column. default=pagetitle + * @param textfield $dir sort direction default=ASC + * @param numberfield $limit Limit the result + * @param combo-boolean $debug if set, will output SQL query for debugging * * Variables * --------- @@ -33,23 +35,26 @@ $core_path = $modx->getOption('taxonomies.core_path', null, MODX_CORE_PATH.'components/taxonomies/'); require_once $core_path .'vendor/autoload.php'; $Snippet = new \Taxonomies\Base($modx); -$Snippet->log('getByTerm',$scriptProperties); +$Snippet->log('getPagesByTerm',$scriptProperties); $debug = $modx->getOption('debug', $scriptProperties); $classname = $modx->getOption('classname', $scriptProperties, 'PageTerm'); -$term_id = $modx->getOption('term_id', $scriptProperties, $modx->resource->get('id')); +$term_id = $modx->getOption('term_id', $scriptProperties); $exact_matches = $modx->getOption('exact_matches', $scriptProperties, false); $graph = $modx->getOption('graph', $scriptProperties, '{"Page":{}}'); $outerTpl = $modx->getOption('outerTpl',$scriptProperties, ''); $innerTpl = $modx->getOption('innerTpl',$scriptProperties, '
  • [[+Page.pagetitle]]
  • '); -$noResultTpl = $modx->getOption('noResultTpl',$scriptProperties, 'No Pages Found.'); -$limit = $modx->getOption('limit', $scriptProperties, null); - $sort = $modx->getOption('sort', $scriptProperties,'pagetitle'); -$dir = $modx->getOption('dir', $scriptProperties,'ASC'); +$dir = $modx->getOption('dir', $scriptProperties,'ASC'); +$limit = $modx->getOption('limit', $scriptProperties, null); +if (!$term_id && isset($modx->resource)) +{ + $term_id = $modx->resource->get('id'); +} -if (!$parent = $modx->getObject('modResource', $term_id)) { +if (!$parent = $modx->getObject('modResource', $term_id)) +{ return 'Invalid Term ID.'; } $filters = array(); @@ -57,14 +62,14 @@ // Append children terms if present $properties = $parent->get('properties'); - -//return print_r($properties,true); -if (!$exact_matches && isset($properties['children_ids'])) { +if (!$exact_matches && isset($properties['children_ids'])) +{ $children_ids = array_keys($properties['children_ids']); $children_ids[] = $term_id; $filters['term_id:IN'] = $children_ids; } -else { +else +{ $filters['term_id'] = $term_id; } @@ -72,12 +77,17 @@ $c = $modx->newQuery($classname); $c->groupby('page_id'); -if (isset($scriptProperties['class_key'])) { +if (isset($scriptProperties['class_key'])) +{ $filters['Page.class_key'] = $scriptProperties['class_key']; } + $c->where($filters); +$c->limit($limit); +$c->sortby($sort,$dir); -if ($debug) { +if ($debug) +{ $c->bindGraph($graph); $c->prepare(); $outerTpl = htmlspecialchars($outerTpl); @@ -96,29 +106,10 @@ '; } -$c->limit($limit); - -$c->sortby($sort,$dir); - -if ($Pages = $modx->getCollectionGraph($classname, $graph,$c)) { +if ($Pages = $modx->getCollectionGraph($classname, $graph,$c)) +{ return $Snippet->format($Pages,$innerTpl,$outerTpl); } -else { - $no_out = ''; - if (!$modx->getObject('modChunk', array('name' => $noResultTpl))) { - // Create the temporary chunk - $uniqid = uniqid(); - $chunk = $modx->newObject('modChunk', array('name' => "{tmp}-{$uniqid}")); - $chunk->setCacheable(false); - - $no_out = $chunk->process(array(), $noResultTpl); - } - // Chunk Name - else { - - $no_out = $modx->getChunk($noResultTpl, array()); - } - return $no_out; -} \ No newline at end of file +return; // null \ No newline at end of file diff --git a/elements/snippets/getTagCloud.php b/elements/snippets/getTagCloud.php old mode 100755 new mode 100644 index d6c7cfb..b85e61e --- a/elements/snippets/getTagCloud.php +++ b/elements/snippets/getTagCloud.php @@ -10,10 +10,12 @@ * * Parameters * ----------------------------- - * @param string $outerTpl Format the Outer Wrapper of List (Optional) - * @param string $innerTpl Format the Inner Item of List - * @param int $limit Limit the result, default to 10 : setting it to 0 will show all - * @param boolean $includeEmpty include all terms (disregard if it's assigned to certain page) + * @param textfield $outerTpl Format the Outer Wrapper of List (Optional) + * @param textfield $innerTpl Format the Inner Item of List + * @param textfield $sort column: pagetitle, id, count + * @param textfield $dir ASC | DESC default=DESC + * @param numberfield $limit Limit the result, default to 10 : setting it to 0 will show all + * @param combo-boolean $includeEmpty include all terms (disregard if it's assigned to certain page) * * Variables * --------- @@ -25,7 +27,7 @@ * [[!getTagCloud? &outerTpl=`sometpl` &innerTpl=`othertpl`]] * * @package taxonomies - **/ + */ $core_path = $modx->getOption('taxonomies.core_path', null, MODX_CORE_PATH.'components/taxonomies/'); require_once $core_path .'vendor/autoload.php'; @@ -33,27 +35,34 @@ $Snippet->log('getTagCloud',$scriptProperties); $includeEmpty = $modx->getOption('includeEmpty',$scriptProperties, 0); +$sort = $modx->getOption('sort',$scriptProperties, 0); +$dir = $modx->getOption('dir',$scriptProperties, 'DESC'); $outerTpl = $modx->getOption('outerTpl',$scriptProperties, ''); $innerTpl = $modx->getOption('innerTpl',$scriptProperties, '
  • [[+pagetitle]] ([[+count]])
  • '); - +$content_table = $modx->getTableName('modResource'); +$pageterms_table = $modx->getTableName('PageTerm'); if($includeEmpty == 1) { - $sql = "SELECT doc.id as id, doc.pagetitle, count(terms.page_id) count - FROM modx_site_content doc - LEFT JOIN tax_page_terms terms ON doc.id = terms.term_id + $sql = "SELECT doc.id as id, doc.pagetitle, count(terms.page_id) as count + FROM $content_table doc + LEFT JOIN $pageterms_table terms ON doc.id = terms.term_id WHERE doc.class_key='Term' GROUP BY doc.id"; } else { - $sql = "SELECT terms.term_id as id, doc.pagetitle, count(*) count - FROM modx_site_content doc - JOIN tax_page_terms terms ON terms.term_id = doc.id + $sql = "SELECT terms.term_id as id, doc.pagetitle, count(*) as count + FROM $content_table doc + JOIN $pageterms_table terms ON terms.term_id = doc.id WHERE doc.class_key='Term' GROUP BY terms.term_id"; } +if($sort) { + $sql.=" ORDER BY $sort $dir"; +} + $obj = $modx->query($sql); $results = $obj->fetchAll(PDO::FETCH_ASSOC); diff --git a/elements/snippets/getTaxonomies.php b/elements/snippets/getTaxonomies.php index 027bfdf..f15049c 100644 --- a/elements/snippets/getTaxonomies.php +++ b/elements/snippets/getTaxonomies.php @@ -10,12 +10,12 @@ * * Parameters * ----------------------------- - * @param string $outerTpl Format the Outer Wrapper of List (Optional) - * @param string $innerTpl Format the Inner Item of List - * @param string $sort column to sort by (default: pagetitle) - * @param string $dir ASC (default) or DESC - * @param integer $limit the max number of records - * @param integer $start the offset + * @param textfield $outerTpl Format the Outer Wrapper of List (Optional) + * @param textfield $innerTpl Format the Inner Item of List + * @param textfield $sort column to sort by default=pagetitle + * @param textfield $dir sorting direction, ASC or DESC default=ASC + * @param numberfield $limit the max number of records + * @param numberfield $start the offset * * Variables * --------- diff --git a/model/Base.php b/model/Base.php index 77d12e1..eeaba4e 100644 --- a/model/Base.php +++ b/model/Base.php @@ -111,8 +111,8 @@ public function format($records, $innerTpl, $outerTpl = null,$separator='') * getTaxonomiesAndTerms : Taxonomies and Terms. BOOM. * * Get data structure describing taxonomy/terms for use in the form. - * TODO: use the json caching here. - * @return array containing structure compatible w Formbuilder: $data['Taxonomy Name']['Term Name'] = page ID + * + * @return array containing structure compatible w Formbuilder: $data['Taxonomy Name'][term_id] = Term Title */ public function getTaxonomiesAndTerms() { @@ -123,18 +123,13 @@ public function getTaxonomiesAndTerms() if ($Ts = $this->modx->getCollection('Taxonomy', $c)) { foreach ($Ts as $t) { - $data[$t->get('pagetitle')] = array(); - $c = $this->modx->newQuery('Term'); - $c->where(array('published' => true, 'class_key' => 'Term', 'parent' => $t->get('id'))); - $c->sortby('menuindex', 'ASC'); - if ($Terms = $this->modx->getCollection('Term', $c)) { - foreach ($Terms as $term) { - $data[$t->get('pagetitle')][$term->get('id')] = $term->get('pagetitle'); - } - } // Plug the spot for the taxonomy? - else { - $data[$t->get('pagetitle')] = array(); + $props = $t->get('properties'); + if (!isset($props['children'])) { + $data[ $t->get('pagetitle') ] = array(); // plug? + continue; } + + $data[ $t->get('pagetitle') ] = $this->extractChildren(array(), $props['children']); } } @@ -142,6 +137,25 @@ public function getTaxonomiesAndTerms() } /** + * wormhole : pulls child data out of JSON cache + */ + public function extractChildren($array, $data, $indent='') + { + foreach ($data as $page_id => $node) { + if (empty($page_id)) { + continue; + } + $array[$page_id] = $indent . ' ' . $node['pagetitle'] .' ('.$page_id.')'; + if ($node['children']) { + $array = $this->extractChildren($array, $node['children'], $indent . '--'); + } + } + + return $array; + } + + /** + * A!#%$ this needs to incorporate the getTaxonomiesAndTerms function * @param array $current_values * @return string */ @@ -182,6 +196,10 @@ public function getFieldItems($current_values,$children, $indent_multiplier = 0, $out = ''; foreach ($children as $page_id => $def) { + if (empty($page_id)) + { + continue; + } $indent = str_repeat('--', $indent_multiplier); if (isset($def['published']) && $def['published']) { diff --git a/tests/taxonomyTest.php b/tests/taxonomyTest.php index adc9a7f..fc9529c 100644 --- a/tests/taxonomyTest.php +++ b/tests/taxonomyTest.php @@ -41,7 +41,13 @@ public static function setUpBeforeClass() self::$modx->initialize('mgr'); //self::$modx->setLogTarget('ECHO'); //self::$modx->setLogLevel(4); - $core_path = self::$modx->getOption('taxonomies.core_path', '', MODX_CORE_PATH . 'components/taxonomies/'); + $pkgs = self::$modx->getOption('extension_packages'); + if (strpos($pkgs, 'taxonomies') === false) + { + die('Taxonomies package not detected in MODX extension_packages. Is the package installed?'); + } + + $core_path = self::$modx->getOption('taxonomies.core_path', '', MODX_CORE_PATH . 'components/taxonomies/'); self::$modx->addExtensionPackage('taxonomies', "{$core_path}model/", array('tablePrefix' => 'tax_')); self::_deleteTestResources(); @@ -177,6 +183,16 @@ public function setUp() self::$PageTerm['2']->save(); } + if (!self::$PageTerm['3'] = self::$modx->getObject('PageTerm', array('term_id' => self::$Term['b']->get('id'), 'page_id' => self::$P['2']->get('id')))) { + self::$PageTerm['3'] = self::$modx->newObject('PageTerm'); + self::$PageTerm['3']->fromArray(array( + 'page_id' => self::$P['2']->get('id'), + 'term_id' => self::$Term['b']->get('id'), + 'seq' => 0 + )); + self::$PageTerm['3']->save(); + } + } /** @@ -419,11 +435,24 @@ public function testFirstGetTagCloud() // You have to do this for EACH test function when you are testing a Snippet! global $modx; $modx = self::$modx; + + // Simple + $props = array(); + $props['innerTpl'] = '
  • [[+pagetitle]] ([[+count]])
  • '; + $props['outerTpl'] = ''; + $actual = self::$modx->runSnippet('getTagCloud', $props); + $expected = ''; + $this->assertEquals($expected, $actual); + + + // Test Sort by Count $props = array(); $props['innerTpl'] = '
  • [[+pagetitle]] ([[+count]])
  • '; $props['outerTpl'] = ''; + $props['sort'] = 'count'; + $props['dir'] = 'DESC'; $actual = self::$modx->runSnippet('getTagCloud', $props); - $expected = ''; + $expected = ''; $this->assertEquals($expected, $actual); } @@ -441,7 +470,7 @@ public function testGetTagCloudIncludeEmpty() $expected = ''; $this->assertTrue( (bool) strpos ($actual, '
  • Test Term A (1)
  • ') ); - $this->assertTrue( (bool) strpos ($actual, '
  • Test Term B (1)
  • ') ); + $this->assertTrue( (bool) strpos ($actual, '
  • Test Term B (2)
  • ') ); $this->assertTrue( (bool) strpos ($actual, '
  • Test Term C (0)
  • ') ); } @@ -681,9 +710,47 @@ public function testFlattenChildrenObjectsToIds() } - public function testGetTaxonomiesAndTerms() + public function testGetPagesByTerm() { + // You MUST set $modx as a global variable, or runSnippet will encounter errors! + // You have to do this for EACH test function when you are testing a Snippet! + // Simple: one page for term A + global $modx; + $modx = self::$modx; + $props = array(); + $props['term_id'] = self::$Term['a']->get('id'); + $actual = self::$modx->runSnippet('getPagesByTerm', $props); + $expected = ''; + $this->assertEquals($expected,$actual); + + // Multiple pages for term B + $props = array(); + $props['term_id'] = self::$Term['b']->get('id'); + $actual = self::$modx->runSnippet('getPagesByTerm', $props); + $expected = ''; + $this->assertEquals(normalize_string($expected),normalize_string($actual)); + // Test limit + $props = array(); + $props['term_id'] = self::$Term['b']->get('id'); + $props['limit'] = 1; + $actual = self::$modx->runSnippet('getPagesByTerm', $props); + $expected = ''; + $this->assertEquals(normalize_string($expected),normalize_string($actual)); + + + // Test sort dir + $props = array(); + $props['term_id'] = self::$Term['b']->get('id'); + $props['dir'] = 'DESC'; + $actual = self::$modx->runSnippet('getPagesByTerm', $props); + $expected = ''; + $this->assertEquals(normalize_string($expected),normalize_string($actual)); + +// +// $this->assertTrue( (bool) strpos ($actual, '
  • Test Term A (1)
  • ') ); +// $this->assertTrue( (bool) strpos ($actual, '
  • Test Term B (1)
  • ') ); +// $this->assertTrue( (bool) strpos ($actual, '
  • Test Term C (0)
  • ') ); } }