diff --git a/code/Controllers/CMSMain.php b/code/Controllers/CMSMain.php
index ae804f4e..8b7e6525 100644
--- a/code/Controllers/CMSMain.php
+++ b/code/Controllers/CMSMain.php
@@ -159,7 +159,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
{
// set reading lang
if (SiteTree::has_extension('Translatable') && !$this->getRequest()->isAjax()) {
- Translatable::choose_site_locale(array_keys(Translatable::get_existing_content_languages('SilverStripe\\CMS\\Model\\SiteTree')));
+ Translatable::choose_site_locale(array_keys(Translatable::get_existing_content_languages(SiteTree::class)));
}
parent::init();
@@ -1734,7 +1734,7 @@ class CMSMain extends LeftAndMain implements CurrentPageIdentifier, PermissionPr
}
/** @var SiteTree $record */
- $record = Versioned::get_one_by_stage('SilverStripe\\CMS\\Model\\SiteTree', 'Live', array(
+ $record = Versioned::get_one_by_stage(SiteTree::class, Versioned::LIVE, array(
'"SiteTree_Live"."ID"' => $id
));
diff --git a/code/Controllers/CMSPageAddController.php b/code/Controllers/CMSPageAddController.php
index fbe893d2..1a529e53 100644
--- a/code/Controllers/CMSPageAddController.php
+++ b/code/Controllers/CMSPageAddController.php
@@ -76,7 +76,7 @@ class CMSPageAddController extends CMSPageEditController
$parentField = new TreeDropdownField(
"ParentID",
"",
- 'SilverStripe\\CMS\\Model\\SiteTree',
+ SiteTree::class,
'ID',
'TreeTitle'
),
diff --git a/code/Controllers/CMSSiteTreeFilter.php b/code/Controllers/CMSSiteTreeFilter.php
index 3e43e78d..e22c0a92 100644
--- a/code/Controllers/CMSSiteTreeFilter.php
+++ b/code/Controllers/CMSSiteTreeFilter.php
@@ -74,7 +74,7 @@ abstract class CMSSiteTreeFilter implements LeftAndMain_SearchFilter
public static function get_all_filters()
{
// get all filter instances
- $filters = ClassInfo::subclassesFor('SilverStripe\\CMS\\Controllers\\CMSSiteTreeFilter');
+ $filters = ClassInfo::subclassesFor(CMSSiteTreeFilter::class);
// remove abstract CMSSiteTreeFilter class
array_shift($filters);
@@ -162,7 +162,7 @@ abstract class CMSSiteTreeFilter implements LeftAndMain_SearchFilter
}
while (!empty($parents)) {
- $q = Versioned::get_including_deleted('SilverStripe\\CMS\\Model\\SiteTree', '"RecordID" in ('.implode(',', array_keys($parents)).')');
+ $q = Versioned::get_including_deleted(SiteTree::class, '"RecordID" in ('.implode(',', array_keys($parents)).')');
$list = $q->map('ID', 'ParentID');
$parents = array();
foreach ($list as $id => $parentID) {
diff --git a/code/Controllers/CMSSiteTreeFilter_ChangedPages.php b/code/Controllers/CMSSiteTreeFilter_ChangedPages.php
index 8fea3517..c37d506d 100644
--- a/code/Controllers/CMSSiteTreeFilter_ChangedPages.php
+++ b/code/Controllers/CMSSiteTreeFilter_ChangedPages.php
@@ -2,6 +2,7 @@
namespace SilverStripe\CMS\Controllers;
+use SilverStripe\CMS\Model\SiteTree;
use SilverStripe\Versioned\Versioned;
/**
@@ -17,7 +18,7 @@ class CMSSiteTreeFilter_ChangedPages extends CMSSiteTreeFilter
public function getFilteredPages()
{
- $pages = Versioned::get_by_stage('SilverStripe\\CMS\\Model\\SiteTree', 'Stage');
+ $pages = Versioned::get_by_stage(SiteTree::class, Versioned::DRAFT);
$pages = $this->applyDefaultFilters($pages)
->leftJoin('SiteTree_Live', '"SiteTree_Live"."ID" = "SiteTree"."ID"')
->where('"SiteTree"."Version" <> "SiteTree_Live"."Version"');
diff --git a/code/Controllers/CMSSiteTreeFilter_DeletedPages.php b/code/Controllers/CMSSiteTreeFilter_DeletedPages.php
index 0e315587..6fb94e94 100644
--- a/code/Controllers/CMSSiteTreeFilter_DeletedPages.php
+++ b/code/Controllers/CMSSiteTreeFilter_DeletedPages.php
@@ -2,6 +2,7 @@
namespace SilverStripe\CMS\Controllers;
+use SilverStripe\CMS\Model\SiteTree;
use SilverStripe\Versioned\Versioned;
/**
@@ -29,7 +30,7 @@ class CMSSiteTreeFilter_DeletedPages extends CMSSiteTreeFilter
public function getFilteredPages()
{
- $pages = Versioned::get_including_deleted('SilverStripe\\CMS\\Model\\SiteTree');
+ $pages = Versioned::get_including_deleted(SiteTree::class);
$pages = $this->applyDefaultFilters($pages);
return $pages;
}
diff --git a/code/Controllers/CMSSiteTreeFilter_PublishedPages.php b/code/Controllers/CMSSiteTreeFilter_PublishedPages.php
index eab67a0e..2efea77b 100644
--- a/code/Controllers/CMSSiteTreeFilter_PublishedPages.php
+++ b/code/Controllers/CMSSiteTreeFilter_PublishedPages.php
@@ -41,7 +41,7 @@ class CMSSiteTreeFilter_PublishedPages extends CMSSiteTreeFilter
*/
public function getFilteredPages()
{
- $pages = Versioned::get_including_deleted('SilverStripe\\CMS\\Model\\SiteTree');
+ $pages = Versioned::get_including_deleted(SiteTree::class);
$pages = $this->applyDefaultFilters($pages);
$pages = $pages->filterByCallback(function (SiteTree $page) {
return $page->isPublished();
diff --git a/code/Controllers/CMSSiteTreeFilter_Search.php b/code/Controllers/CMSSiteTreeFilter_Search.php
index abc3975f..f36ee187 100644
--- a/code/Controllers/CMSSiteTreeFilter_Search.php
+++ b/code/Controllers/CMSSiteTreeFilter_Search.php
@@ -1,6 +1,7 @@
applyDefaultFilters($pages);
return $pages;
}
diff --git a/code/Controllers/CMSSiteTreeFilter_StatusDeletedPages.php b/code/Controllers/CMSSiteTreeFilter_StatusDeletedPages.php
index 1a46eda5..f83732df 100644
--- a/code/Controllers/CMSSiteTreeFilter_StatusDeletedPages.php
+++ b/code/Controllers/CMSSiteTreeFilter_StatusDeletedPages.php
@@ -35,7 +35,7 @@ class CMSSiteTreeFilter_StatusDeletedPages extends CMSSiteTreeFilter
*/
public function getFilteredPages()
{
- $pages = Versioned::get_including_deleted('SilverStripe\\CMS\\Model\\SiteTree');
+ $pages = Versioned::get_including_deleted(SiteTree::class);
$pages = $this->applyDefaultFilters($pages);
$pages = $pages->filterByCallback(function (SiteTree $page) {
diff --git a/code/Controllers/CMSSiteTreeFilter_StatusDraftPages.php b/code/Controllers/CMSSiteTreeFilter_StatusDraftPages.php
index a8f9b736..0279f380 100644
--- a/code/Controllers/CMSSiteTreeFilter_StatusDraftPages.php
+++ b/code/Controllers/CMSSiteTreeFilter_StatusDraftPages.php
@@ -25,7 +25,7 @@ class CMSSiteTreeFilter_StatusDraftPages extends CMSSiteTreeFilter
*/
public function getFilteredPages()
{
- $pages = Versioned::get_by_stage('SilverStripe\\CMS\\Model\\SiteTree', 'Stage');
+ $pages = Versioned::get_by_stage(SiteTree::class, 'Stage');
$pages = $this->applyDefaultFilters($pages);
$pages = $pages->filterByCallback(function (SiteTree $page) {
// If page exists on stage but not on live
diff --git a/code/Controllers/CMSSiteTreeFilter_StatusRemovedFromDraftPages.php b/code/Controllers/CMSSiteTreeFilter_StatusRemovedFromDraftPages.php
index c9f11abe..41afb042 100644
--- a/code/Controllers/CMSSiteTreeFilter_StatusRemovedFromDraftPages.php
+++ b/code/Controllers/CMSSiteTreeFilter_StatusRemovedFromDraftPages.php
@@ -24,7 +24,7 @@ class CMSSiteTreeFilter_StatusRemovedFromDraftPages extends CMSSiteTreeFilter
*/
public function getFilteredPages()
{
- $pages = Versioned::get_including_deleted('SilverStripe\\CMS\\Model\\SiteTree');
+ $pages = Versioned::get_including_deleted(SiteTree::class);
$pages = $this->applyDefaultFilters($pages);
$pages = $pages->filterByCallback(function (SiteTree $page) {
// If page is removed from stage but not live
diff --git a/code/Controllers/ContentController.php b/code/Controllers/ContentController.php
index 7467a71d..d1ff25b3 100644
--- a/code/Controllers/ContentController.php
+++ b/code/Controllers/ContentController.php
@@ -108,7 +108,7 @@ class ContentController extends Controller
$parent = SiteTree::get_by_link($parentRef);
if (!$parent && is_numeric($parentRef)) {
- $parent = DataObject::get_by_id('SilverStripe\\CMS\\Model\\SiteTree', $parentRef);
+ $parent = DataObject::get_by_id(SiteTree::class, $parentRef);
}
if ($parent) {
diff --git a/code/Controllers/LeftAndMainPageIconsExtension.php b/code/Controllers/LeftAndMainPageIconsExtension.php
index 6e8cbf89..7044c2e3 100644
--- a/code/Controllers/LeftAndMainPageIconsExtension.php
+++ b/code/Controllers/LeftAndMainPageIconsExtension.php
@@ -2,6 +2,7 @@
namespace SilverStripe\CMS\Controllers;
+use SilverStripe\CMS\Model\SiteTree;
use SilverStripe\Core\Convert;
use SilverStripe\View\Requirements;
use SilverStripe\Core\ClassInfo;
@@ -29,7 +30,7 @@ class LeftAndMainPageIconsExtension extends Extension
{
$css = '';
- $classes = ClassInfo::subclassesFor('SilverStripe\\CMS\\Model\\SiteTree');
+ $classes = ClassInfo::subclassesFor(SiteTree::class);
foreach ($classes as $class) {
$obj = singleton($class);
$iconSpec = $obj->config()->get('icon');
diff --git a/code/Controllers/ModelAsController.php b/code/Controllers/ModelAsController.php
index 742f3ddc..bd828ae2 100644
--- a/code/Controllers/ModelAsController.php
+++ b/code/Controllers/ModelAsController.php
@@ -49,7 +49,7 @@ class ModelAsController extends Controller implements NestedController
protected function init()
{
- singleton('SilverStripe\\CMS\\Model\\SiteTree')->extend('modelascontrollerInit', $this);
+ singleton(SiteTree::class)->extend('modelascontrollerInit', $this);
parent::init();
}
diff --git a/code/Controllers/SilverStripeNavigator.php b/code/Controllers/SilverStripeNavigator.php
index 6de775b5..a71fc288 100644
--- a/code/Controllers/SilverStripeNavigator.php
+++ b/code/Controllers/SilverStripeNavigator.php
@@ -43,8 +43,8 @@ class SilverStripeNavigator extends ViewableData
{
$items = array();
- $classes = ClassInfo::subclassesFor('SilverStripe\\CMS\\Controllers\\SilverStripeNavigatorItem');
- unset($classes['SilverStripe\\CMS\\Controllers\\SilverStripeNavigatorItem']);
+ $classes = ClassInfo::subclassesFor(SilverStripeNavigatorItem::class);
+ array_shift($classes);
// Sort menu items according to priority
foreach ($classes as $class) {
diff --git a/code/Model/SiteTree.php b/code/Model/SiteTree.php
index 818de5ff..49d2c3ad 100755
--- a/code/Model/SiteTree.php
+++ b/code/Model/SiteTree.php
@@ -2488,17 +2488,18 @@ class SiteTree extends DataObject implements PermissionProvider, i18nEntityProvi
// Parse candidate list
$allowedChildren = [];
- foreach ($candidates as $candidate) {
+ foreach ((array)$candidates as $candidate) {
// If a classname is prefixed by "*", such as "*Page", then only that class is allowed - no subclasses.
// Otherwise, the class and all its subclasses are allowed.
if (substr($candidate, 0, 1) == '*') {
$allowedChildren[] = substr($candidate, 1);
- } elseif ($subclasses = ClassInfo::subclassesFor($candidate)) {
+ } elseif (($candidate !== 'SiteTree_root')
+ && ($subclasses = ClassInfo::subclassesFor($candidate))
+ ) {
foreach ($subclasses as $subclass) {
- if ($subclass == 'SiteTree_root' || singleton($subclass) instanceof HiddenClass) {
- continue;
+ if (!is_a($subclass, HiddenClass::class, true)) {
+ $allowedChildren[] = $subclass;
}
- $allowedChildren[] = $subclass;
}
}
static::$_allowedChildren[get_class($this)] = $allowedChildren;
diff --git a/code/Model/SiteTreeFileExtension.php b/code/Model/SiteTreeFileExtension.php
index 57731896..9e208992 100644
--- a/code/Model/SiteTreeFileExtension.php
+++ b/code/Model/SiteTreeFileExtension.php
@@ -3,11 +3,9 @@
namespace SilverStripe\CMS\Model;
use SilverStripe\Assets\File;
-use SilverStripe\Core\Convert;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\ReadonlyField;
use SilverStripe\ORM\DataExtension;
-use SilverStripe\ORM\DataObject;
use SilverStripe\ORM\ManyManyList;
use SilverStripe\Versioned\Versioned;
use SilverStripe\View\SSViewer;
@@ -25,9 +23,8 @@ use Subsite;
*/
class SiteTreeFileExtension extends DataExtension
{
-
private static $belongs_many_many = array(
- 'BackLinkTracking' => 'SilverStripe\\CMS\\Model\\SiteTree.ImageTracking' // {@see SiteTreeLinkTracking}
+ 'BackLinkTracking' => SiteTree::class . '.ImageTracking' // {@see SiteTreeLinkTracking}
);
/**
@@ -122,7 +119,7 @@ class SiteTreeFileExtension extends DataExtension
$brokenPageIDs = $this->owner->BackLinkTracking()->column("ID");
if ($brokenPageIDs) {
// This will syncLinkTracking on the same stage as this file
- $brokenPages = DataObject::get('SilverStripe\\CMS\\Model\\SiteTree')->byIDs($brokenPageIDs);
+ $brokenPages = SiteTree::get()->byIDs($brokenPageIDs);
foreach ($brokenPages as $brokenPage) {
$brokenPage->write();
}
diff --git a/code/Model/SiteTreeFolderExtension.php b/code/Model/SiteTreeFolderExtension.php
index 59264b86..a119ea3d 100644
--- a/code/Model/SiteTreeFolderExtension.php
+++ b/code/Model/SiteTreeFolderExtension.php
@@ -2,61 +2,73 @@
namespace SilverStripe\CMS\Model;
+use SilverStripe\Assets\File;
+use SilverStripe\Assets\Folder;
use SilverStripe\Core\ClassInfo;
-use SilverStripe\ORM\DB;
-use SilverStripe\ORM\DataQuery;
-use SilverStripe\ORM\DataList;
+use SilverStripe\Core\Config\Config;
+use SilverStripe\Core\Convert;
+use SilverStripe\ORM\ArrayList;
use SilverStripe\ORM\DataExtension;
+use SilverStripe\ORM\DataList;
+use SilverStripe\ORM\DataObject;
+use SilverStripe\ORM\DB;
-/**
- * @todo Cleanup, refactor, test this class
- */
class SiteTreeFolderExtension extends DataExtension
{
-
/**
* Looks for files used in system and create where clause which contains all ID's of files.
*
- * @returns String where clause which will work as filter.
+ * @returns string where clause which will work as filter.
*/
public function getUnusedFilesListFilter()
{
- $result = DB::query("SELECT DISTINCT \"FileID\" FROM \"SiteTree_ImageTracking\"");
- $usedFiles = array();
- $where = '';
- $classes = ClassInfo::subclassesFor('SilverStripe\\CMS\\Model\\SiteTree');
+ // Add all records in link tracking
+ $usedFiles = DB::query("SELECT DISTINCT \"FileID\" FROM \"SiteTree_ImageTracking\"")->column('FileID');
- if ($result->numRecords() > 0) {
- while ($nextResult = $result->next()) {
- $where .= $nextResult['FileID'] . ',';
- }
- }
+ // Get all classes that aren't folder
+ $fileClasses = array_diff_key(
+ ClassInfo::subclassesFor(File::class),
+ ClassInfo::subclassesFor(Folder::class)
+ );
+ // Search on a class-by-class basis
+ $classes = ClassInfo::subclassesFor(SiteTree::class);
+
+ $schema = DataObject::getSchema();
foreach ($classes as $className) {
- $query = new DataQuery($className);
- $ids = $query->execute()->column();
- if (!count($ids)) {
+ // Build query based on all direct has_ones on this class
+ $hasOnes = Config::inst()->get($className, 'has_one', Config::UNINHERITED);
+ if (empty($hasOnes)) {
continue;
}
-
- foreach (singleton($className)->hasOne() as $relName => $joinClass) {
- if ($joinClass == 'SilverStripe\\Assets\\Image' || $joinClass == 'SilverStripe\\Assets\\File') {
- $fieldName = $relName .'ID';
- $query = DataList::create($className)->where("$fieldName > 0");
- $query->distinct = true;
- $query->select(array($fieldName));
- $usedFiles = array_merge($usedFiles, $query->execute()->column());
- } elseif ($joinClass == 'SilverStripe\\Assets\\Folder') {
- // @todo
+ $where = [];
+ $columns = [];
+ foreach ($hasOnes as $relName => $joinClass) {
+ if (in_array($joinClass, $fileClasses)) {
+ $column = $relName . 'ID';
+ $columns[] = $column;
+ $quotedColumn = $schema->sqlColumnForField($className, $column);
+ $where[] = "{$quotedColumn} > 0";
}
}
+
+ // Get all records with any file ID in the searched columns
+ $recordsArray = DataList::create($className)->whereAny($where)->toArray();
+ $records = ArrayList::create($recordsArray);
+ foreach ($columns as $column) {
+ $usedFiles = array_unique(array_merge($usedFiles, $records->column($column)));
+ }
}
+ // Create filter based on class and id
+ $classFilter = sprintf(
+ "(\"File\".\"ClassName\" IN (%s))",
+ implode(", ", Convert::raw2sql($fileClasses, true))
+ );
if ($usedFiles) {
- return "\"File\".\"ID\" NOT IN (" . implode(', ', $usedFiles) . ") AND (\"ClassName\" = 'File' OR \"ClassName\" = 'Image')";
+ return "\"File\".\"ID\" NOT IN (" . implode(', ', $usedFiles) . ") AND $classFilter";
} else {
- return "(\"ClassName\" = 'File' OR \"ClassName\" = 'Image')";
+ return $classFilter;
}
- return $where; // @todo - How?
}
}
diff --git a/code/Model/SiteTreeLinkTracking_Parser.php b/code/Model/SiteTreeLinkTracking_Parser.php
index 9b081950..7066ad7f 100644
--- a/code/Model/SiteTreeLinkTracking_Parser.php
+++ b/code/Model/SiteTreeLinkTracking_Parser.php
@@ -56,7 +56,7 @@ class SiteTreeLinkTracking_Parser
// Link to a page on this site.
$matches = array();
if (preg_match('/\[sitetree_link(?:\s*|%20|,)?id=(?
[image id="%d"]
', + $imageID + ); + $page->write(); + } + + public function tearDown() + { + TestAssetStore::reset(); + parent::tearDown(); + } + + public function testFindsFiles() + { + /** @var PageWithFile $page */ + $page = $this->objFromFixture(PageWithFile::class, 'page1'); + $query = $page->getUnusedFilesListFilter(); + $this->assertContains('"ID" NOT IN', $query); + $this->assertContains('"ClassName" IN (', $query); + + $files = File::get()->where($query); + $this->assertDOSEquals( + [ + ['Name' => 'file2.txt'], + ['Name' => 'image2.jpg'], + ], + $files + ); + } +} diff --git a/tests/php/Model/SiteTreeFolderExtensionTest.yml b/tests/php/Model/SiteTreeFolderExtensionTest.yml new file mode 100644 index 00000000..fa7605da --- /dev/null +++ b/tests/php/Model/SiteTreeFolderExtensionTest.yml @@ -0,0 +1,28 @@ +SilverStripe\Assets\Folder: + folder1: + Name: myfolder + folder2: + Name: other +SilverStripe\Assets\File: + file1: + Name: file1.txt + FileFilename: myfolder/file1.txt + Parent: =>SilverStripe\Assets\Folder.folder1 + file2: + Name: file2.txt + FileFilename: myfolder/file2.txt + Parent: =>SilverStripe\Assets\Folder.folder1 +SilverStripe\Assets\Image: + image1: + Name: image1.jpg + FileFilename: other/image1.jpg + Parent: =>SilverStripe\Assets\Folder.folder2 + image2: + Name: image2.jpg + FileFilename: other/image2.jpg + Parent: =>SilverStripe\Assets\Folder.folder2 +SilverStripe\CMS\Tests\Model\SiteTreeFolderExtensionTest\PageWithFile: + page1: + Title: mypage + URLSegment: mypage + LinkedFile: =>SilverStripe\Assets\File.file1 diff --git a/tests/php/Model/SiteTreeFolderExtensionTest/PageWithFile.php b/tests/php/Model/SiteTreeFolderExtensionTest/PageWithFile.php new file mode 100644 index 00000000..1d6d845b --- /dev/null +++ b/tests/php/Model/SiteTreeFolderExtensionTest/PageWithFile.php @@ -0,0 +1,24 @@ + File::class, + ]; + + private static $extensions = [ + SiteTreeFolderExtension::class, + ]; +}