Completed
Pull Request — master (#293)
by Robbie
01:51
created

FileSubsites::augmentSQL()   C

Complexity

Conditions 7
Paths 7

Size

Total Lines 34
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 34
rs 6.7272
c 0
b 0
f 0
cc 7
eloc 17
nc 7
nop 2
1
<?php
2
3
namespace SilverStripe\Subsites\Extensions;
4
5
use SilverStripe\Assets\Folder;
6
use SilverStripe\Control\Session;
7
use SilverStripe\Forms\DropdownField;
8
use SilverStripe\Forms\FieldList;
9
use SilverStripe\Forms\LiteralField;
10
use SilverStripe\ORM\DataExtension;
11
use SilverStripe\ORM\DataQuery;
12
use SilverStripe\ORM\Queries\SQLSelect;
13
use SilverStripe\Security\Permission;
14
use SilverStripe\Subsites\Model\Subsite;
15
use SilverStripe\Subsites\State\SubsiteState;
16
17
/**
18
 * Extension for the File object to add subsites support
19
 *
20
 * @package subsites
21
 */
22
class FileSubsites extends DataExtension
23
{
24
    // If this is set to true, all folders created will be default be
25
    // considered 'global', unless set otherwise
26
    public static $default_root_folders_global = false;
27
28
    private static $has_one = [
0 ignored issues
show
Unused Code introduced by
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...
29
        'Subsite' => Subsite::class,
30
    ];
31
32
    /**
33
     * Amends the CMS tree title for folders in the Files & Images section.
34
     * Prefixes a '* ' to the folders that are accessible from all subsites.
35
     */
36
    public function alternateTreeTitle()
37
    {
38
        if ($this->owner->SubsiteID == 0) {
39
            return ' * ' . $this->owner->Title;
40
        }
41
42
        return $this->owner->Title;
43
    }
44
45
    /**
46
     * Add subsites-specific fields to the folder editor.
47
     * @param FieldList $fields
48
     */
49
    public function updateCMSFields(FieldList $fields)
50
    {
51
        if ($this->owner instanceof Folder) {
52
            $sites = Subsite::accessible_sites('CMS_ACCESS_AssetAdmin');
53
            $values = [];
54
            $values[0] = _t('FileSubsites.AllSitesDropdownOpt', 'All sites');
55
            foreach ($sites as $site) {
56
                $values[$site->ID] = $site->Title;
57
            }
58
            ksort($values);
59
            if ($sites) {
60
                //Dropdown needed to move folders between subsites
61
                $dropdown = new DropdownField(
62
                    'SubsiteID',
63
                    _t('FileSubsites.SubsiteFieldLabel', Subsite::class),
64
                    $values
65
                );
66
                $dropdown->addExtraClass('subsites-move-dropdown');
67
                $fields->push($dropdown);
68
                $fields->push(new LiteralField(
69
                    'Message',
70
                    '<p class="message notice">' .
71
                    _t(
72
                        'ASSETADMIN.SUBSITENOTICE',
73
                        'Folders and files created in the main site are accessible by all subsites.'
74
                    )
75
                    . '</p>'
76
                ));
77
            }
78
        }
79
    }
80
81
    /**
82
     * Update any requests to limit the results to the current site
83
     * @param SQLSelect $query
84
     * @param DataQuery|null $dataQuery
85
     */
86
    public function augmentSQL(SQLSelect $query, DataQuery $dataQuery = null)
87
    {
88
        if (Subsite::$disable_subsite_filter) {
89
            return;
90
        }
91
92
        // If you're querying by ID, ignore the sub-site - this is a bit ugly... (but it was WAYYYYYYYYY worse)
93
        //@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
94
95
        $from = $query->getFrom();
96
        if (isset($from['SiteTree_ImageTracking']) || $query->filtersOnID()) {
97
            return;
98
        }
99
100
        $subsiteID = SubsiteState::singleton()->getSubsiteId();
101
        if ($subsiteID === null) {
102
            return;
103
        }
104
105
        // The foreach is an ugly way of getting the first key :-)
106
        foreach ($query->getFrom() as $tableName => $info) {
107
            $where = "\"$tableName\".\"SubsiteID\" IN (0, $subsiteID)";
108
            $query->addWhere($where);
109
            break;
110
        }
111
112
        $sect = array_values($query->getSelect());
113
        $isCounting = strpos($sect[0], 'COUNT') !== false;
114
115
        // Ordering when deleting or counting doesn't apply
116
        if (!$isCounting) {
117
            $query->addOrderBy('"SubsiteID"');
118
        }
119
    }
120
121
    public function onBeforeWrite()
122
    {
123
        if (!$this->owner->ID && !$this->owner->SubsiteID) {
124
            if (self::$default_root_folders_global) {
125
                $this->owner->SubsiteID = 0;
126
            } else {
127
                $this->owner->SubsiteID = SubsiteState::singleton()->getSubsiteId();
128
            }
129
        }
130
    }
131
132
    public function onAfterUpload()
133
    {
134
        // If we have a parent, use it's subsite as our subsite
135
        if ($this->owner->Parent()) {
136
            $this->owner->SubsiteID = $this->owner->Parent()->SubsiteID;
137
        } else {
138
            $this->owner->SubsiteID = SubsiteState::singleton()->getSubsiteId();
139
        }
140
        $this->owner->write();
141
    }
142
143
    public function canEdit($member = null)
144
    {
145
        // Check the CMS_ACCESS_SecurityAdmin privileges on the subsite that owns this group
146
        $subsiteID = SubsiteState::singleton()->getSubsiteId();
147
        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...
148
            return true;
149
        }
150
151
        return SubsiteState::singleton()->withState(function ($newState) {
152
            $newState->setSubsiteId($this->owner->SubsiteID);
153
154
            return Permission::check(['CMS_ACCESS_AssetAdmin', 'CMS_ACCESS_LeftAndMain']);
155
        });
156
    }
157
158
    /**
159
     * Return a piece of text to keep DataObject cache keys appropriately specific
160
     *
161
     * @return string
162
     */
163
    public function cacheKeyComponent()
164
    {
165
        return 'subsite-' . SubsiteState::singleton()->getSubsiteId();
166
    }
167
}
168