Completed
Push — master ( 60b259...83077f )
by Will
01:57
created

code/extensions/FileSubsites.php (2 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace SilverStripe\Subsites\Extensions;
4
5
use SilverStripe\Assets\Folder;
6
use SilverStripe\Forms\DropdownField;
7
use SilverStripe\Forms\FieldList;
8
use SilverStripe\Forms\LiteralField;
9
use SilverStripe\ORM\DataExtension;
10
use SilverStripe\ORM\DataQuery;
11
use SilverStripe\ORM\Queries\SQLSelect;
12
use SilverStripe\Security\Permission;
13
use SilverStripe\Subsites\Model\Subsite;
14
use SilverStripe\Subsites\State\SubsiteState;
15
16
/**
17
 * Extension for the File object to add subsites support
18
 *
19
 * @package subsites
20
 */
21
class FileSubsites extends DataExtension
22
{
23
    // If this is set to true, all folders created will be default be
24
    // considered 'global', unless set otherwise
25
    public static $default_root_folders_global = false;
26
27
    private static $has_one = [
0 ignored issues
show
The property $has_one is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
28
        'Subsite' => Subsite::class,
29
    ];
30
31
    /**
32
     * Amends the CMS tree title for folders in the Files & Images section.
33
     * Prefixes a '* ' to the folders that are accessible from all subsites.
34
     */
35
    public function alternateTreeTitle()
36
    {
37
        if ($this->owner->SubsiteID == 0) {
38
            return ' * ' . $this->owner->Title;
39
        }
40
41
        return $this->owner->Title;
42
    }
43
44
    /**
45
     * Add subsites-specific fields to the folder editor.
46
     * @param FieldList $fields
47
     */
48
    public function updateCMSFields(FieldList $fields)
49
    {
50
        if ($this->owner instanceof Folder) {
51
            $sites = Subsite::accessible_sites('CMS_ACCESS_AssetAdmin');
52
            $values = [];
53
            $values[0] = _t('FileSubsites.AllSitesDropdownOpt', 'All sites');
54
            foreach ($sites as $site) {
55
                $values[$site->ID] = $site->Title;
56
            }
57
            ksort($values);
58
            if ($sites) {
59
                //Dropdown needed to move folders between subsites
60
                $dropdown = new DropdownField(
61
                    'SubsiteID',
62
                    _t('FileSubsites.SubsiteFieldLabel', Subsite::class),
63
                    $values
64
                );
65
                $dropdown->addExtraClass('subsites-move-dropdown');
66
                $fields->push($dropdown);
67
                $fields->push(new LiteralField(
68
                    'Message',
69
                    '<p class="message notice">' .
70
                    _t(
71
                        'ASSETADMIN.SUBSITENOTICE',
72
                        'Folders and files created in the main site are accessible by all subsites.'
73
                    )
74
                    . '</p>'
75
                ));
76
            }
77
        }
78
    }
79
80
    /**
81
     * Update any requests to limit the results to the current site
82
     * @param SQLSelect $query
83
     * @param DataQuery|null $dataQuery
84
     */
85
    public function augmentSQL(SQLSelect $query, DataQuery $dataQuery = null)
86
    {
87
        if (Subsite::$disable_subsite_filter) {
88
            return;
89
        }
90
91
        // If you're querying by ID, ignore the sub-site - this is a bit ugly... (but it was WAYYYYYYYYY worse)
92
        //@TODO I don't think excluding if SiteTree_ImageTracking is a good idea however because of the SS 3.0 api and ManyManyList::removeAll() changing the from table after this function is called there isn't much of a choice
93
94
        $from = $query->getFrom();
95
        if (isset($from['SiteTree_ImageTracking']) || $query->filtersOnID()) {
96
            return;
97
        }
98
99
        $subsiteID = SubsiteState::singleton()->getSubsiteId();
100
        if ($subsiteID === null) {
101
            return;
102
        }
103
104
        // The foreach is an ugly way of getting the first key :-)
105
        foreach ($query->getFrom() as $tableName => $info) {
106
            $where = "\"$tableName\".\"SubsiteID\" IN (0, $subsiteID)";
107
            $query->addWhere($where);
108
            break;
109
        }
110
111
        $sect = array_values($query->getSelect());
112
        $isCounting = strpos($sect[0], 'COUNT') !== false;
113
114
        // Ordering when deleting or counting doesn't apply
115
        if (!$isCounting) {
116
            $query->addOrderBy('"SubsiteID"');
117
        }
118
    }
119
120
    public function onBeforeWrite()
121
    {
122
        if (!$this->owner->ID && !$this->owner->SubsiteID) {
123
            if (self::$default_root_folders_global) {
124
                $this->owner->SubsiteID = 0;
125
            } else {
126
                $this->owner->SubsiteID = SubsiteState::singleton()->getSubsiteId();
127
            }
128
        }
129
    }
130
131
    public function onAfterUpload()
132
    {
133
        // If we have a parent, use it's subsite as our subsite
134
        if ($this->owner->Parent()) {
135
            $this->owner->SubsiteID = $this->owner->Parent()->SubsiteID;
136
        } else {
137
            $this->owner->SubsiteID = SubsiteState::singleton()->getSubsiteId();
138
        }
139
        $this->owner->write();
140
    }
141
142
    public function canEdit($member = null)
143
    {
144
        // Check the CMS_ACCESS_SecurityAdmin privileges on the subsite that owns this group
145
        $subsiteID = SubsiteState::singleton()->getSubsiteId();
146
        if ($subsiteID && $subsiteID == $this->owner->SubsiteID) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $subsiteID of type integer|null is loosely compared to true; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
147
            return true;
148
        }
149
150
        return SubsiteState::singleton()->withState(function ($newState) {
151
            $newState->setSubsiteId($this->owner->SubsiteID);
152
153
            return Permission::check(['CMS_ACCESS_AssetAdmin', 'CMS_ACCESS_LeftAndMain']);
154
        });
155
    }
156
157
    /**
158
     * Return a piece of text to keep DataObject cache keys appropriately specific
159
     *
160
     * @return string
161
     */
162
    public function cacheKeyComponent()
163
    {
164
        return 'subsite-' . SubsiteState::singleton()->getSubsiteId();
165
    }
166
}
167