diff --git a/modules/cms/classes/CmsObjectCollection.php b/modules/cms/classes/CmsObjectCollection.php index 6f2099eec..b89703d4d 100644 --- a/modules/cms/classes/CmsObjectCollection.php +++ b/modules/cms/classes/CmsObjectCollection.php @@ -16,14 +16,81 @@ class CmsObjectCollection extends CollectionBase * @param string|array $components * @return static */ - public function withComponent($components) + public function withComponent($components, $callback = null) { - return $this->filter(function($object) use ($components) { + return $this->filter(function($object) use ($components, $callback) { $hasComponent = false; - foreach ((array) $components as $component) { - if ($object->hasComponent($component)) { + foreach ((array) $components as $componentName) { + + if (!$callback && $object->hasComponent($componentName)) { + $hasComponent = true; + } + + if ($callback && ($component = $object->getComponent($componentName))) { + $hasComponent = call_user_func($callback, $component) ?: $hasComponent; + } + } + + return $hasComponent; + }); + } + + /** + * Returns objects whose properties match the supplied value. + * @param string $property + * @param string $value + * @return static + */ + public function where($property, $value, $strict = true) + { + return $this->filter(function($object) use ($property, $value, $strict) { + + if (!array_key_exists($property, $object->settings)) { + return false; + } + + return $strict + ? $object->settings[$property] === $value + : $object->settings[$property] == $value; + }); + } + + /** + * Returns objects whose component properties match the supplied value. + * @param string $property + * @param string $value + * @return static + */ + public function whereComponent($components, $property, $value, $strict = true) + { + return $this->filter(function($object) use ($components, $property, $value, $strict) { + + $hasComponent = false; + + foreach ((array) $components as $componentName) { + + if (!$componentAlias = $object->hasComponent($componentName)) { + continue; + } + + $componentSettings = array_get($object->settings, 'components', []); + + if (!array_key_exists($componentAlias, $componentSettings)) { + continue; + } + + $settings = $componentSettings[$componentAlias]; + + if (!array_key_exists($property, $settings)) { + continue; + } + + if ( + ($strict && $settings[$property] === $value) || + (!$strict && $settings[$property] == $value) + ) { $hasComponent = true; } } @@ -31,4 +98,5 @@ class CmsObjectCollection extends CollectionBase return $hasComponent; }); } + } diff --git a/modules/cms/classes/CmsObjectQuery.php b/modules/cms/classes/CmsObjectQuery.php index a057c0d0c..e801bc059 100644 --- a/modules/cms/classes/CmsObjectQuery.php +++ b/modules/cms/classes/CmsObjectQuery.php @@ -40,6 +40,10 @@ class CmsObjectQuery */ public function inTheme($theme) { + if (is_string($theme)) { + $theme = Theme::load($theme); + } + $this->theme = $theme; return $this; } diff --git a/tests/unit/cms/classes/CmsObjectQueryTest.php b/tests/unit/cms/classes/CmsObjectQueryTest.php new file mode 100644 index 000000000..65ca650b3 --- /dev/null +++ b/tests/unit/cms/classes/CmsObjectQueryTest.php @@ -0,0 +1,95 @@ +first(); + $this->assertEquals('/no-layout', $page->url); + } + + public function testWhereComponent() + { + include_once base_path() . '/tests/fixtures/plugins/october/tester/components/Archive.php'; + + $pages = Page::whereComponent('testArchive', 'posts-per-page', '6'); + $this->assertCount(1, $pages->all()); + + $page = $pages->first(); + $this->assertEquals('/with-components', $page->url); + } + + public function testWithComponent() + { + $pages = Page::withComponent('testArchive')->all(); + $this->assertCount(2, $pages); + foreach ($pages as $page) { + $this->assertTrue(!!$page->hasComponent('testArchive')); + } + } + + public function testWithComponentCallback() + { + include_once base_path() . '/tests/fixtures/plugins/october/tester/components/Archive.php'; + + $pages = Page::withComponent('testArchive', function($component) { + return $component->property('posts-per-page') == '69'; + })->all(); + + $this->assertCount(1, $pages); + } + + public function testLists() + { + // Default theme: test + $pages = Page::lists('baseFileName'); + $this->assertEquals([ + "404", + "a/a-page", + "ajax-test", + "authors", + "b/b-page", + "blog-archive", + "blog-post", + "code-namespaces", + "component-custom-render", + "component-partial-nesting", + "component-partial-override", + "component-partial", + "cycle-test", + "index", + "no-component-class", + "no-component", + "no-layout", + "no-partial", + "optional-full-php-tags", + "optional-short-php-tags", + "throw-php", + "with-component", + "with-components", + "with-content", + "with-layout", + "with-partials", + "with-placeholder", + ], $pages); + + $layouts = Layout::lists('baseFileName'); + $this->assertEquals([ + "a/a-layout", + "ajax-test", + "content", + "cycle-test", + "no-php", + "partials", + "php-parser-test", + "placeholder", + "sidebar", + ], $layouts); + + $pages = Page::inTheme('NON_EXISTENT_THEME')->lists('baseFileName'); + $this->assertEmpty($pages); + } +}