Completed
Push — master ( 2e2112...bbe9e3 )
by Franco
01:12 queued 01:07
created

DMSDocument::getRelatedDocumentsGridField()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 18
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 18
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 11
nc 1
nop 0
1
<?php
2
3
/**
4
 * @package dms
5
 */
6
class DMSDocument extends DataObject implements DMSDocumentInterface
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
7
{
8
    private static $db = array(
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
Unused Code introduced by
The property $db 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...
9
        "Filename" => "Varchar(255)", // eg. 3469~2011-energysaving-report.pdf
10
        "Folder" => "Varchar(255)",    // eg.	0
11
        "Title" => 'Varchar(1024)', // eg. "Energy Saving Report for Year 2011, New Zealand LandCorp"
12
        "Description" => 'Text',
13
        "ViewCount" => 'Int',
14
        // When this document's file was created or last replaced (small changes like updating title don't count)
15
        "LastChanged" => 'SS_DateTime',
16
17
        "EmbargoedIndefinitely" => 'Boolean(false)',
18
        "EmbargoedUntilPublished" => 'Boolean(false)',
19
        "EmbargoedUntilDate" => 'SS_DateTime',
20
        "ExpireAtDate" => 'SS_DateTime',
21
        "DownloadBehavior" => 'Enum(array("open","download"), "download")',
22
    );
23
24
    private static $many_many = array(
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
Unused Code introduced by
The property $many_many 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...
25
        'Pages' => 'SiteTree',
26
        'RelatedDocuments' => 'DMSDocument',
27
        'Tags' => 'DMSTag'
28
    );
29
30
    private static $many_many_extraFields = array(
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
Unused Code introduced by
The property $many_many_extraFields 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...
31
        'Pages' => array(
32
            'DocumentSort' => 'Int'
33
        )
34
    );
35
36
    private static $display_fields = array(
0 ignored issues
show
Unused Code introduced by
The property $display_fields 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...
37
        'ID' => 'ID',
38
        'Title' => 'Title',
39
        'FilenameWithoutID' => 'Filename',
40
        'LastChanged' => 'LastChanged'
41
    );
42
43
    private static $singular_name = 'Document';
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
Unused Code introduced by
The property $singular_name 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...
44
45
    private static $plural_name = 'Documents';
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
Unused Code introduced by
The property $plural_name 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...
46
47
    private static $searchable_fields = array(
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
Unused Code introduced by
The property $searchable_fields 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...
48
        'ID' => array(
49
            'filter' => 'ExactMatchFilter',
50
            'field' => 'NumericField'
51
        ),
52
        'Title',
53
        'Filename',
54
        'LastChanged'
55
    );
56
57
    /**
58
     * @var string download|open
59
     * @config
60
     */
61
    private static $default_download_behaviour = 'download';
0 ignored issues
show
Unused Code introduced by
The property $default_download_behaviour 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...
62
63
    /**
64
     * @param Member $member
0 ignored issues
show
Documentation introduced by
Should the type for parameter $member not be Member|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
65
     *
66
     * @return boolean
67
     */
68
    public function canView($member = null)
69
    {
70
        if (!$member || !(is_a($member, 'Member')) || is_numeric($member)) {
71
            $member = Member::currentUser();
72
        }
73
74
        // extended access checks
75
        $results = $this->extend('canView', $member);
76
77
        if ($results && is_array($results)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $results of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
78
            if (!min($results)) {
79
                return false;
80
            }
81
        }
82
83
        if ($member && $member->ID) {
0 ignored issues
show
Unused Code introduced by
This if statement, and the following return statement can be replaced with return $member && $member->ID;.
Loading history...
84
            return true;
85
        }
86
87
        return false;
88
    }
89
90
    /**
91
     * @param Member $member
0 ignored issues
show
Documentation introduced by
Should the type for parameter $member not be Member|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
92
     *
93
     * @return boolean
94
     */
95 View Code Duplication
    public function canEdit($member = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
96
    {
97
        if (!$member || !(is_a($member, 'Member')) || is_numeric($member)) {
98
            $member = Member::currentUser();
99
        }
100
101
        $results = $this->extend('canEdit', $member);
102
103
        if ($results && is_array($results)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $results of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
104
            if (!min($results)) {
105
                return false;
106
            }
107
        }
108
109
        return $this->canView();
110
    }
111
112
    /**
113
     * @param Member $member
0 ignored issues
show
Documentation introduced by
Should the type for parameter $member not be Member|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
114
     *
115
     * @return boolean
116
     */
117 View Code Duplication
    public function canCreate($member = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
118
    {
119
        if (!$member || !(is_a($member, 'Member')) || is_numeric($member)) {
120
            $member = Member::currentUser();
121
        }
122
123
        $results = $this->extend('canCreate', $member);
124
125
        if ($results && is_array($results)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $results of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
126
            if (!min($results)) {
127
                return false;
128
            }
129
        }
130
131
        return $this->canView();
132
    }
133
134
    /**
135
     * @param Member $member
0 ignored issues
show
Documentation introduced by
Should the type for parameter $member not be Member|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
136
     *
137
     * @return boolean
138
     */
139 View Code Duplication
    public function canDelete($member = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
140
    {
141
        if (!$member || !(is_a($member, 'Member')) || is_numeric($member)) {
142
            $member = Member::currentUser();
143
        }
144
145
        $results = $this->extend('canDelete', $member);
146
147
        if ($results && is_array($results)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $results of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
148
            if (!min($results)) {
149
                return false;
150
            }
151
        }
152
153
        return $this->canView();
154
    }
155
156
157
158
    /**
159
     * Associates this document with a Page. This method does nothing if the
160
     * association already exists.
161
     *
162
     * This could be a simple wrapper around $myDoc->Pages()->add($myPage) to
163
     * add a many_many relation.
164
     *
165
     * @param SiteTree $pageObject Page object to associate this Document with
166
     *
167
     * @return DMSDocument
168
     */
169
    public function addPage($pageObject)
170
    {
171
        $this->Pages()->add($pageObject);
172
173
        DB::query(
174
            "UPDATE \"DMSDocument_Pages\" SET \"DocumentSort\"=\"DocumentSort\"+1"
175
            . " WHERE \"SiteTreeID\" = $pageObject->ID"
176
        );
177
178
        return $this;
179
    }
180
181
    /**
182
     * Associates this DMSDocument with a set of Pages. This method loops
183
     * through a set of page ids, and then associates this DMSDocument with the
184
     * individual Page with the each page id in the set.
185
     *
186
     * @param array $pageIDs
187
     *
188
     * @return DMSDocument
189
     */
190
    public function addPages($pageIDs)
191
    {
192
        foreach ($pageIDs as $id) {
193
            $pageObject = DataObject::get_by_id("SiteTree", $id);
194
195
            if ($pageObject && $pageObject->exists()) {
196
                $this->addPage($pageObject);
0 ignored issues
show
Compatibility introduced by
$pageObject of type object<DataObject> is not a sub-type of object<SiteTree>. It seems like you assume a child class of the class DataObject to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
197
            }
198
        }
199
200
        return $this;
201
    }
202
203
    /**
204
     * Removes the association between this Document and a Page. This method
205
     * does nothing if the association does not exist.
206
     *
207
     * @param SiteTree $pageObject Page object to remove the association to
208
     *
209
     * @return DMSDocument
210
     */
211
    public function removePage($pageObject)
212
    {
213
        $this->Pages()->remove($pageObject);
0 ignored issues
show
Documentation introduced by
$pageObject is of type object<SiteTree>, but the function expects a object<DataClass>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
214
215
        return $this;
216
    }
217
218
    /**
219
     * @see getPages()
220
     *
221
     * @return DataList
222
     */
223
    public function Pages()
224
    {
225
        $pages = $this->getManyManyComponents('Pages');
226
        $this->extend('updatePages', $pages);
227
228
        return $pages;
229
    }
230
231
    /**
232
     * Returns a list of the Page objects associated with this Document.
233
     *
234
     * @return DataList
235
     */
236
    public function getPages()
237
    {
238
        return $this->Pages();
239
    }
240
241
    /**
242
     * Removes all associated Pages from the DMSDocument
243
     *
244
     * @return DMSDocument
245
     */
246
    public function removeAllPages()
247
    {
248
        $this->Pages()->removeAll();
249
250
        return $this;
251
    }
252
253
    /**
254
     * Increase ViewCount by 1, without update any other record fields such as
255
     * LastEdited.
256
     *
257
     * @return DMSDocument
258
     */
259
    public function trackView()
260
    {
261
        if ($this->ID > 0) {
262
            $count = $this->ViewCount + 1;
0 ignored issues
show
Documentation introduced by
The property ViewCount does not exist on object<DMSDocument>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
263
264
            $this->ViewCount = $count;
0 ignored issues
show
Documentation introduced by
The property ViewCount does not exist on object<DMSDocument>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
265
266
            DB::query("UPDATE \"DMSDocument\" SET \"ViewCount\"='$count' WHERE \"ID\"={$this->ID}");
267
        }
268
269
        return $this;
270
    }
271
272
273
    /**
274
     * Adds a metadata tag to the Document. The tag has a category and a value.
275
     *
276
     * Each category can have multiple values by default. So:
277
     * addTag("fruit","banana") addTag("fruit", "apple") will add two items.
278
     *
279
     * However, if the third parameter $multiValue is set to 'false', then all
280
     * updates to a category only ever update a single value. So:
281
     * addTag("fruit","banana") addTag("fruit", "apple") would result in a
282
     * single metadata tag: fruit->apple.
283
     *
284
     * Can could be implemented as a key/value store table (although it is more
285
     * like category/value, because the same category can occur multiple times)
286
     *
287
     * @param string $category of a metadata category to add (required)
288
     * @param string $value of a metadata value to add (required)
289
     * @param bool $multiValue Boolean that determines if the category is
290
     * 					multi-value or single-value (optional)
291
     *
292
     * @return DMSDocument
293
     */
294
    public function addTag($category, $value, $multiValue = true)
295
    {
296
        if ($multiValue) {
297
            //check for a duplicate tag, don't add the duplicate
298
            $currentTag = $this->Tags()->filter(array('Category' => $category, 'Value' => $value));
0 ignored issues
show
Documentation Bug introduced by
The method Tags does not exist on object<DMSDocument>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
299
            if ($currentTag->Count() == 0) {
300
                //multi value tag
301
                $tag = new DMSTag();
302
                $tag->Category = $category;
0 ignored issues
show
Documentation introduced by
The property Category does not exist on object<DMSTag>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
303
                $tag->Value = $value;
0 ignored issues
show
Documentation introduced by
The property Value does not exist on object<DMSTag>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
304
                $tag->MultiValue = true;
0 ignored issues
show
Documentation introduced by
The property MultiValue does not exist on object<DMSTag>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
305
                $tag->write();
306
                $tag->Documents()->add($this);
0 ignored issues
show
Documentation Bug introduced by
The method Documents does not exist on object<DMSTag>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
307
            } else {
308
                //add the relation between the tag and document
309
                foreach ($currentTag as $tagObj) {
310
                    $tagObj->Documents()->add($this);
311
                }
312
            }
313
        } else {
314
            //single value tag
315
            $currentTag = $this->Tags()->filter(array('Category' => $category));
0 ignored issues
show
Documentation Bug introduced by
The method Tags does not exist on object<DMSDocument>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
316
            $tag = null;
0 ignored issues
show
Unused Code introduced by
$tag is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
317
            if ($currentTag->Count() == 0) {
318
                //create the single-value tag
319
                $tag = new DMSTag();
320
                $tag->Category = $category;
0 ignored issues
show
Documentation introduced by
The property Category does not exist on object<DMSTag>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
321
                $tag->Value = $value;
0 ignored issues
show
Documentation introduced by
The property Value does not exist on object<DMSTag>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
322
                $tag->MultiValue = false;
0 ignored issues
show
Documentation introduced by
The property MultiValue does not exist on object<DMSTag>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
323
                $tag->write();
324
            } else {
325
                //update the single value tag
326
                $tag = $currentTag->first();
327
                $tag->Value = $value;
328
                $tag->MultiValue = false;
329
                $tag->write();
330
            }
331
332
            // regardless of whether we created a new tag or are just updating an
333
            // existing one, add the relation
334
            $tag->Documents()->add($this);
335
        }
336
337
        return $this;
338
    }
339
340
    /**
341
     * @param string $category
342
     * @param string $value
0 ignored issues
show
Documentation introduced by
Should the type for parameter $value not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
343
     *
344
     * @return DataList
345
     */
346
    protected function getTagsObjects($category, $value = null)
347
    {
348
        $valueFilter = array("Category" => $category);
349
        if (!empty($value)) {
350
            $valueFilter['Value'] = $value;
351
        }
352
353
        $tags = $this->Tags()->filter($valueFilter);
0 ignored issues
show
Documentation Bug introduced by
The method Tags does not exist on object<DMSDocument>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
354
        return $tags;
355
    }
356
357
    /**
358
     * Fetches all tags associated with this DMSDocument within a given
359
     * category. If a value is specified this method tries to fetch that
360
     * specific tag.
361
     *
362
     * @param string $category metadata category to get
363
     * @param string $value value of the tag to get
0 ignored issues
show
Documentation introduced by
Should the type for parameter $value not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
364
     *
365
     * @return array Strings of all the tags or null if there is no match found
0 ignored issues
show
Documentation introduced by
Should the return type not be array|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
366
     */
367
    public function getTagsList($category, $value = null)
368
    {
369
        $tags = $this->getTagsObjects($category, $value);
370
371
        $returnArray = null;
372
373
        if ($tags->Count() > 0) {
374
            $returnArray = array();
375
376
            foreach ($tags as $t) {
377
                $returnArray[] = $t->Value;
378
            }
379
        }
380
381
        return $returnArray;
382
    }
383
384
    /**
385
     * Removes a tag from the Document. If you only set a category, then all
386
     * values in that category are deleted.
387
     *
388
     * If you specify both a category and a value, then only that single
389
     * category/value pair is deleted.
390
     *
391
     * Nothing happens if the category or the value do not exist.
392
     *
393
     * @param string $category Category to remove
394
     * @param string $value Value to remove
0 ignored issues
show
Documentation introduced by
Should the type for parameter $value not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
395
     *
396
     * @return DMSDocument
397
     */
398
    public function removeTag($category, $value = null)
399
    {
400
        $tags = $this->getTagsObjects($category, $value);
401
402
        if ($tags->Count() > 0) {
403
            foreach ($tags as $t) {
404
                $documentList = $t->Documents();
405
406
                //remove the relation between the tag and the document
407
                $documentList->remove($this);
408
409
                //delete the entire tag if it has no relations left
410
                if ($documentList->Count() == 0) {
411
                    $t->delete();
412
                }
413
            }
414
        }
415
416
        return $this;
417
    }
418
419
    /**
420
     * Deletes all tags associated with this Document.
421
     *
422
     * @return DMSDocument
423
     */
424
    public function removeAllTags()
425
    {
426
        $allTags = $this->Tags();
0 ignored issues
show
Documentation Bug introduced by
The method Tags does not exist on object<DMSDocument>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
427
428
        foreach ($allTags as $tag) {
429
            $documentlist = $tag->Documents();
430
            $documentlist->remove($this);
431
            if ($tag->Documents()->Count() == 0) {
432
                $tag->delete();
433
            }
434
        }
435
436
        return $this;
437
    }
438
439
    /**
440
     * Returns a link to download this document from the DMS store.
441
     *
442
     * @return string
443
     */
444
    public function getLink()
445
    {
446
        return Controller::join_links(Director::baseURL(), 'dmsdocument/'.$this->ID);
447
    }
448
449
    /**
450
     * @return string
451
     */
452
    public function Link()
453
    {
454
        return $this->getLink();
455
    }
456
457
    /**
458
     * Hides the document, so it does not show up when getByPage($myPage) is
459
     * called (without specifying the $showEmbargoed = true parameter).
460
     *
461
     * This is similar to expire, except that this method should be used to hide
462
     * documents that have not yet gone live.
463
     *
464
     * @param bool $write Save change to the database
465
     *
466
     * @return DMSDocument
467
     */
468
    public function embargoIndefinitely($write = true)
469
    {
470
        $this->EmbargoedIndefinitely = true;
0 ignored issues
show
Documentation introduced by
The property EmbargoedIndefinitely does not exist on object<DMSDocument>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
471
472
        if ($write) {
473
            $this->write();
474
        }
475
476
        return $this;
477
    }
478
479
    /**
480
     * Hides the document until any page it is linked to is published
481
     *
482
     * @param bool $write Save change to database
483
     *
484
     * @return DMSDocument
485
     */
486
    public function embargoUntilPublished($write = true)
487
    {
488
        $this->EmbargoedUntilPublished = true;
0 ignored issues
show
Documentation introduced by
The property EmbargoedUntilPublished does not exist on object<DMSDocument>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
489
490
        if ($write) {
491
            $this->write();
492
        }
493
494
        return $this;
495
    }
496
497
    /**
498
     * Returns if this is Document is embargoed or expired.
499
     *
500
     * Also, returns if the document should be displayed on the front-end,
501
     * respecting the current reading mode of the site and the embargo status.
502
     *
503
     * I.e. if a document is embargoed until published, then it should still
504
     * show up in draft mode.
505
     *
506
     * @return bool
507
     */
508
    public function isHidden()
509
    {
510
        $hidden = $this->isEmbargoed() || $this->isExpired();
511
        $readingMode = Versioned::get_reading_mode();
512
513
        if ($readingMode == "Stage.Stage") {
514
            if ($this->EmbargoedUntilPublished == true) {
0 ignored issues
show
Documentation introduced by
The property EmbargoedUntilPublished does not exist on object<DMSDocument>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
515
                $hidden = false;
516
            }
517
        }
518
519
        return $hidden;
520
    }
521
522
    /**
523
     * Returns if this is Document is embargoed.
524
     *
525
     * @return bool
526
     */
527
    public function isEmbargoed()
528
    {
529
        if (is_object($this->EmbargoedUntilDate)) {
0 ignored issues
show
Documentation introduced by
The property EmbargoedUntilDate does not exist on object<DMSDocument>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
530
            $this->EmbargoedUntilDate = $this->EmbargoedUntilDate->Value;
0 ignored issues
show
Documentation introduced by
The property EmbargoedUntilDate does not exist on object<DMSDocument>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
Documentation introduced by
The property EmbargoedUntilDate does not exist on object<DMSDocument>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
531
        }
532
533
        $embargoed = false;
534
535
        if ($this->EmbargoedIndefinitely) {
0 ignored issues
show
Documentation introduced by
The property EmbargoedIndefinitely does not exist on object<DMSDocument>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
536
            $embargoed = true;
537
        } elseif ($this->EmbargoedUntilPublished) {
0 ignored issues
show
Documentation introduced by
The property EmbargoedUntilPublished does not exist on object<DMSDocument>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
538
            $embargoed = true;
539
        } elseif (!empty($this->EmbargoedUntilDate)) {
0 ignored issues
show
Documentation introduced by
The property EmbargoedUntilDate does not exist on object<DMSDocument>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
540
            if (SS_Datetime::now()->Value < $this->EmbargoedUntilDate) {
0 ignored issues
show
Documentation introduced by
The property EmbargoedUntilDate does not exist on object<DMSDocument>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
541
                $embargoed = true;
542
            }
543
        }
544
545
        return $embargoed;
546
    }
547
548
    /**
549
     * Hides the document, so it does not show up when getByPage($myPage) is
550
     * called. Automatically un-hides the Document at a specific date.
551
     *
552
     * @param string $datetime date time value when this Document should expire.
553
     * @param bool $write
554
     *
555
     * @return DMSDocument
556
     */
557 View Code Duplication
    public function embargoUntilDate($datetime, $write = true)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
558
    {
559
        $this->EmbargoedUntilDate = DBField::create_field('SS_Datetime', $datetime)->Format('Y-m-d H:i:s');
0 ignored issues
show
Documentation introduced by
The property EmbargoedUntilDate does not exist on object<DMSDocument>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
560
561
        if ($write) {
562
            $this->write();
563
        }
564
565
        return $this;
566
    }
567
568
    /**
569
     * Clears any previously set embargos, so the Document always shows up in
570
     * all queries.
571
     *
572
     * @param bool $write
573
     *
574
     * @return DMSDocument
575
     */
576
    public function clearEmbargo($write = true)
577
    {
578
        $this->EmbargoedIndefinitely = false;
0 ignored issues
show
Documentation introduced by
The property EmbargoedIndefinitely does not exist on object<DMSDocument>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
579
        $this->EmbargoedUntilPublished = false;
0 ignored issues
show
Documentation introduced by
The property EmbargoedUntilPublished does not exist on object<DMSDocument>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
580
        $this->EmbargoedUntilDate = null;
0 ignored issues
show
Documentation introduced by
The property EmbargoedUntilDate does not exist on object<DMSDocument>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
581
582
        if ($write) {
583
            $this->write();
584
        }
585
586
        return $this;
587
    }
588
589
    /**
590
     * Returns if this is Document is expired.
591
     *
592
     * @return bool
593
     */
594
    public function isExpired()
595
    {
596
        if (is_object($this->ExpireAtDate)) {
0 ignored issues
show
Documentation introduced by
The property ExpireAtDate does not exist on object<DMSDocument>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
597
            $this->ExpireAtDate = $this->ExpireAtDate->Value;
0 ignored issues
show
Documentation introduced by
The property ExpireAtDate does not exist on object<DMSDocument>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
Documentation introduced by
The property ExpireAtDate does not exist on object<DMSDocument>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
598
        }
599
600
        $expired = false;
601
602
        if (!empty($this->ExpireAtDate)) {
0 ignored issues
show
Documentation introduced by
The property ExpireAtDate does not exist on object<DMSDocument>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
603
            if (SS_Datetime::now()->Value >= $this->ExpireAtDate) {
0 ignored issues
show
Documentation introduced by
The property ExpireAtDate does not exist on object<DMSDocument>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
604
                $expired = true;
605
            }
606
        }
607
608
        return $expired;
609
    }
610
611
    /**
612
     * Hides the document at a specific date, so it does not show up when
613
     * getByPage($myPage) is called.
614
     *
615
     * @param string $datetime date time value when this Document should expire
616
     * @param bool $write
617
     *
618
     * @return DMSDocument
619
     */
620 View Code Duplication
    public function expireAtDate($datetime, $write = true)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
621
    {
622
        $this->ExpireAtDate = DBField::create_field('SS_Datetime', $datetime)->Format('Y-m-d H:i:s');
0 ignored issues
show
Documentation introduced by
The property ExpireAtDate does not exist on object<DMSDocument>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
623
624
        if ($write) {
625
            $this->write();
626
        }
627
628
        return $this;
629
    }
630
631
    /**
632
     * Clears any previously set expiry.
633
     *
634
     * @param bool $write
635
     *
636
     * @return DMSDocument
637
     */
638
    public function clearExpiry($write = true)
639
    {
640
        $this->ExpireAtDate = null;
0 ignored issues
show
Documentation introduced by
The property ExpireAtDate does not exist on object<DMSDocument>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
641
642
        if ($write) {
643
            $this->write();
644
        }
645
646
        return $this;
647
    }
648
649
    /**
650
     * Returns a DataList of all previous Versions of this document (check the
651
     * LastEdited date of each object to find the correct one).
652
     *
653
     * If {@link DMSDocument_versions::$enable_versions} is disabled then an
654
     * Exception is thrown
655
     *
656
     * @throws Exception
657
     *
658
     * @return DataList List of Document objects
659
     */
660
    public function getVersions()
661
    {
662
        if (!DMSDocument_versions::$enable_versions) {
663
            throw new Exception("DMSDocument versions are disabled");
664
        }
665
666
        return DMSDocument_versions::get_versions($this);
667
    }
668
669
    /**
670
     * Returns the full filename of the document stored in this object.
671
     *
672
     * @return string
0 ignored issues
show
Documentation introduced by
Should the return type not be string|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
673
     */
674
    public function getFullPath()
675
    {
676
        if ($this->Filename) {
0 ignored issues
show
Documentation introduced by
The property Filename does not exist on object<DMSDocument>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
677
            return DMS::get_dms_path() . DIRECTORY_SEPARATOR . $this->Folder . DIRECTORY_SEPARATOR . $this->Filename;
0 ignored issues
show
Documentation introduced by
The property Folder does not exist on object<DMSDocument>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
Documentation introduced by
The property Filename does not exist on object<DMSDocument>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
678
        }
679
680
        return null;
681
    }
682
683
    /**
684
     * Returns the filename of this asset.
685
     *
686
     * @return string
687
     */
688
    public function getFileName()
689
    {
690
        if ($this->getField('Filename')) {
691
            return $this->getField('Filename');
692
        } else {
693
            return ASSETS_DIR . '/';
694
        }
695
    }
696
697
    /**
698
     * @return string
699
     */
700
    public function getName()
701
    {
702
        return $this->getField('Title');
703
    }
704
705
706
    /**
707
     * @return string
708
     */
709
    public function getFilenameWithoutID()
710
    {
711
        $filenameParts = explode('~', $this->Filename);
0 ignored issues
show
Documentation introduced by
The property Filename does not exist on object<DMSDocument>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
712
        $filename = array_pop($filenameParts);
713
714
        return $filename;
715
    }
716
717
    /**
718
     * @return string
719
     */
720
    public function getStorageFolder()
721
    {
722
        return DMS::get_dms_path() . DIRECTORY_SEPARATOR . DMS::get_storage_folder($this->ID);
723
    }
724
725
    /**
726
     * Deletes the DMSDocument, its underlying file, as well as any tags related
727
     * to this DMSDocument. Also calls the parent DataObject's delete method in
728
     * order to complete an cascade.
729
     *
730
     * @return void
731
     */
732
    public function delete()
733
    {
734
        // remove tags
735
        $this->removeAllTags();
736
737
        // delete the file (and previous versions of files)
738
        $filesToDelete = array();
739
        $storageFolder = $this->getStorageFolder();
740
741
        if (file_exists($storageFolder)) {
742
            if ($handle = opendir($storageFolder)) {
743
                while (false !== ($entry = readdir($handle))) {
744
                    // only delete if filename starts the the relevant ID
745
                    if (strpos($entry, $this->ID.'~') === 0) {
746
                        $filesToDelete[] = $entry;
747
                    }
748
                }
749
750
                closedir($handle);
751
752
                //delete all this files that have the id of this document
753
                foreach ($filesToDelete as $file) {
754
                    $filePath = $storageFolder .DIRECTORY_SEPARATOR . $file;
755
756
                    if (is_file($filePath)) {
757
                        unlink($filePath);
758
                    }
759
                }
760
            }
761
        }
762
763
        $this->removeAllPages();
764
765
        // get rid of any versions have saved for this DMSDocument, too
766
        if (DMSDocument_versions::$enable_versions) {
767
            $versions = $this->getVersions();
768
769
            if ($versions->Count() > 0) {
770
                foreach ($versions as $v) {
771
                    $v->delete();
772
                }
773
            }
774
        }
775
776
        parent::delete();
777
    }
778
779
780
781
    /**
782
     * Relate an existing file on the filesystem to the document.
783
     *
784
     * Copies the file to the new destination, as defined in {@link get_DMS_path()}.
785
     *
786
     * @param string $filePath Path to file, relative to webroot.
787
     *
788
     * @return DMSDocument
789
     */
790
    public function storeDocument($filePath)
791
    {
792
        if (empty($this->ID)) {
793
            user_error("Document must be written to database before it can store documents", E_USER_ERROR);
794
        }
795
796
        // calculate all the path to copy the file to
797
        $fromFilename = basename($filePath);
798
        $toFilename = $this->ID. '~' . $fromFilename; //add the docID to the start of the Filename
799
        $toFolder = DMS::get_storage_folder($this->ID);
800
        $toPath = DMS::get_dms_path() . DIRECTORY_SEPARATOR . $toFolder . DIRECTORY_SEPARATOR . $toFilename;
801
802
        DMS::create_storage_folder(DMS::get_dms_path() . DIRECTORY_SEPARATOR . $toFolder);
803
804
        //copy the file into place
805
        $fromPath = BASE_PATH . DIRECTORY_SEPARATOR . $filePath;
806
807
        //version the existing file (copy it to a new "very specific" filename
808
        if (DMSDocument_versions::$enable_versions) {
809
            DMSDocument_versions::create_version($this);
810
        } else {    //otherwise delete the old document file
811
            $oldPath = $this->getFullPath();
812
            if (file_exists($oldPath)) {
813
                unlink($oldPath);
814
            }
815
        }
816
817
        copy($fromPath, $toPath);   //this will overwrite the existing file (if present)
818
819
        //write the filename of the stored document
820
        $this->Filename = $toFilename;
0 ignored issues
show
Documentation introduced by
The property Filename does not exist on object<DMSDocument>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
821
        $this->Folder = strval($toFolder);
0 ignored issues
show
Documentation introduced by
The property Folder does not exist on object<DMSDocument>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
822
823
        $extension = pathinfo($this->Filename, PATHINFO_EXTENSION);
0 ignored issues
show
Documentation introduced by
The property Filename does not exist on object<DMSDocument>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
824
825
        if (empty($this->Title)) {
0 ignored issues
show
Documentation introduced by
The property Title does not exist on object<DMSDocument>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
826
            // don't overwrite existing document titles
827
            $this->Title = basename($filePath, '.'.$extension);
0 ignored issues
show
Documentation introduced by
The property Title does not exist on object<DMSDocument>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
828
        }
829
830
        $this->LastChanged = SS_Datetime::now()->Rfc2822();
0 ignored issues
show
Bug introduced by
The property LastChanged does not seem to exist. Did you mean changed?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
831
        $this->write();
832
833
        return $this;
834
    }
835
836
    /**
837
     * Takes a File object or a String (path to a file) and copies it into the
838
     * DMS, replacing the original document file but keeping the rest of the
839
     * document unchanged.
840
     *
841
     * @param File|string $file path to a file to store
842
     *
843
     * @return DMSDocument object that we replaced the file in
844
     */
845
    public function replaceDocument($file)
846
    {
847
        $filePath = DMS::transform_file_to_file_path($file);
848
        $doc = $this->storeDocument($filePath); // replace the document
849
850
        return $doc;
851
    }
852
853
854
    /**
855
     * Return the type of file for the given extension
856
     * on the current file name.
857
     *
858
     * @param string $ext
859
     *
860
     * @return string
861
     */
862
    public static function get_file_type($ext)
863
    {
864
        $types = array(
865
            'gif' => 'GIF image - good for diagrams',
866
            'jpg' => 'JPEG image - good for photos',
867
            'jpeg' => 'JPEG image - good for photos',
868
            'png' => 'PNG image - good general-purpose format',
869
            'ico' => 'Icon image',
870
            'tiff' => 'Tagged image format',
871
            'doc' => 'Word document',
872
            'xls' => 'Excel spreadsheet',
873
            'zip' => 'ZIP compressed file',
874
            'gz' => 'GZIP compressed file',
875
            'dmg' => 'Apple disk image',
876
            'pdf' => 'Adobe Acrobat PDF file',
877
            'mp3' => 'MP3 audio file',
878
            'wav' => 'WAV audo file',
879
            'avi' => 'AVI video file',
880
            'mpg' => 'MPEG video file',
881
            'mpeg' => 'MPEG video file',
882
            'js' => 'Javascript file',
883
            'css' => 'CSS file',
884
            'html' => 'HTML file',
885
            'htm' => 'HTML file'
886
        );
887
888
        return isset($types[$ext]) ? $types[$ext] : $ext;
889
    }
890
891
892
    /**
893
     * Returns the Description field with HTML <br> tags added when there is a
894
     * line break.
895
     *
896
     * @return string
897
     */
898
    public function getDescriptionWithLineBreak()
899
    {
900
        return nl2br($this->getField('Description'));
901
    }
902
903
    /**
904
     * @return FieldList
905
     */
906
    public function getCMSFields()
907
    {
908
        //include JS to handling showing and hiding of bottom "action" tabs
909
        Requirements::javascript(DMS_DIR.'/javascript/DMSDocumentCMSFields.js');
910
        Requirements::css(DMS_DIR.'/css/DMSDocumentCMSFields.css');
911
912
        $fields = new FieldList();  //don't use the automatic scaffolding, it is slow and unnecessary here
913
914
        $extraTasks = '';   //additional text to inject into the list of tasks at the bottom of a DMSDocument CMSfield
915
916
        //get list of shortcode page relations
917
        $relationFinder = new ShortCodeRelationFinder();
918
        $relationList = $relationFinder->getList($this->ID);
919
920
        $fieldsTop = $this->getFieldsForFile($relationList->count());
921
        $fields->add($fieldsTop);
922
923
        $fields->add(new TextField('Title', 'Title'));
924
        $fields->add(new TextareaField('Description', 'Description'));
925
926
        $downloadBehaviorSource = array(
927
            'open' => _t('DMSDocument.OPENINBROWSER', 'Open in browser'),
928
            'download' => _t('DMSDocument.FORCEDOWNLOAD', 'Force download'),
929
        );
930
        $defaultDownloadBehaviour = Config::inst()->get('DMSDocument', 'default_download_behaviour');
931
        if (!isset($downloadBehaviorSource[$defaultDownloadBehaviour])) {
932
            user_error('Default download behaviour "' . $defaultDownloadBehaviour . '" not supported.', E_USER_WARNING);
933
        } else {
934
            $downloadBehaviorSource[$defaultDownloadBehaviour] .= ' (' . _t('DMSDocument.DEFAULT', 'default') . ')';
935
        }
936
937
        $fields->add(
938
            OptionsetField::create(
939
                'DownloadBehavior',
940
                _t('DMSDocument.DOWNLOADBEHAVIOUR', 'Download behavior'),
941
                $downloadBehaviorSource,
942
                $defaultDownloadBehaviour
943
            )
944
            ->setDescription(
945
                'How the visitor will view this file. <strong>Open in browser</strong> '
946
                . 'allows files to be opened in a new tab.'
947
            )
948
        );
949
950
        //create upload field to replace document
951
        $uploadField = new DMSUploadField('ReplaceFile', 'Replace file');
952
        $uploadField->setConfig('allowedMaxFileNumber', 1);
953
        $uploadField->setConfig('downloadTemplateName', 'ss-dmsuploadfield-downloadtemplate');
954
        $uploadField->setRecord($this);
955
956
        $gridFieldConfig = GridFieldConfig::create()->addComponents(
957
            new GridFieldToolbarHeader(),
958
            new GridFieldSortableHeader(),
959
            new GridFieldDataColumns(),
960
            new GridFieldPaginator(30),
961
            //new GridFieldEditButton(),
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
962
            new GridFieldDetailForm()
963
        );
964
965
        $gridFieldConfig->getComponentByType('GridFieldDataColumns')
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface GridFieldComponent as the method setDisplayFields() does only exist in the following implementations of said interface: GridFieldDataColumns, GridFieldEditableColumns, GridFieldExternalLink.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
966
            ->setDisplayFields(array(
967
                'Title'=>'Title',
968
                'ClassName'=>'Page Type',
969
                'ID'=>'Page ID'
970
            ))
971
            ->setFieldFormatting(array(
972
                'Title'=>sprintf(
973
                    '<a class=\"cms-panel-link\" href=\"%s/$ID\">$Title</a>',
974
                    singleton('CMSPageEditController')->Link('show')
975
                )
976
            ));
977
978
        $pagesGrid = GridField::create(
979
            'Pages',
980
            _t('DMSDocument.RelatedPages', 'Related Pages'),
981
            $this->Pages(),
982
            $gridFieldConfig
983
        );
984
985
        $referencesGrid = GridField::create(
986
            'References',
987
            _t('DMSDocument.RelatedReferences', 'Related References'),
988
            $relationList,
989
            $gridFieldConfig
990
        );
991
992
        if (DMSDocument_versions::$enable_versions) {
993
            $versionsGridFieldConfig = GridFieldConfig::create()->addComponents(
994
                new GridFieldToolbarHeader(),
995
                new GridFieldSortableHeader(),
996
                new GridFieldDataColumns(),
997
                new GridFieldPaginator(30)
998
            );
999
            $versionsGridFieldConfig->getComponentByType('GridFieldDataColumns')
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface GridFieldComponent as the method setDisplayFields() does only exist in the following implementations of said interface: GridFieldDataColumns, GridFieldEditableColumns, GridFieldExternalLink.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
1000
                ->setDisplayFields(Config::inst()->get('DMSDocument_versions', 'display_fields'))
1001
                ->setFieldCasting(array('LastChanged'=>"Datetime->Ago"))
1002
                ->setFieldFormatting(
1003
                    array(
1004
                        'FilenameWithoutID' => '<a target=\'_blank\' class=\'file-url\' href=\'$Link\'>'
1005
                            . '$FilenameWithoutID</a>'
1006
                    )
1007
                );
1008
1009
            $versionsGrid =  GridField::create(
1010
                'Versions',
1011
                _t('DMSDocument.Versions', 'Versions'),
1012
                $this->getVersions(),
1013
                $versionsGridFieldConfig
1014
            );
1015
            $extraTasks .= '<li class="ss-ui-button" data-panel="find-versions">Versions</li>';
1016
        }
1017
1018
        $fields->add(new LiteralField(
1019
            'BottomTaskSelection',
1020
            '<div id="Actions" class="field actions"><label class="left">Actions</label><ul>'
1021
            . '<li class="ss-ui-button" data-panel="embargo">Embargo</li>'
1022
            . '<li class="ss-ui-button" data-panel="expiry">Expiry</li>'
1023
            . '<li class="ss-ui-button" data-panel="replace">Replace</li>'
1024
            . '<li class="ss-ui-button" data-panel="find-usage">Usage</li>'
1025
            . '<li class="ss-ui-button" data-panel="find-references">References</li>'
1026
            . '<li class="ss-ui-button" data-panel="find-relateddocuments">Related Documents</li>'
1027
            . $extraTasks
1028
            . '</ul></div>'
1029
        ));
1030
1031
        $embargoValue = 'None';
1032
        if ($this->EmbargoedIndefinitely) {
0 ignored issues
show
Documentation introduced by
The property EmbargoedIndefinitely does not exist on object<DMSDocument>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
1033
            $embargoValue = 'Indefinitely';
1034
        } elseif ($this->EmbargoedUntilPublished) {
0 ignored issues
show
Documentation introduced by
The property EmbargoedUntilPublished does not exist on object<DMSDocument>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
1035
            $embargoValue = 'Published';
1036
        } elseif (!empty($this->EmbargoedUntilDate)) {
0 ignored issues
show
Documentation introduced by
The property EmbargoedUntilDate does not exist on object<DMSDocument>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
1037
            $embargoValue = 'Date';
1038
        }
1039
        $embargo = new OptionsetField(
1040
            'Embargo',
1041
            'Embargo',
1042
            array(
1043
                'None' => 'None',
1044
                'Published' => 'Hide document until page is published',
1045
                'Indefinitely' => 'Hide document indefinitely',
1046
                'Date' => 'Hide until set date'
1047
            ),
1048
            $embargoValue
1049
        );
1050
        $embargoDatetime = DatetimeField::create('EmbargoedUntilDate', '');
1051
        $embargoDatetime->getDateField()
1052
            ->setConfig('showcalendar', true)
1053
            ->setConfig('dateformat', 'dd-MM-yyyy')
1054
            ->setConfig('datavalueformat', 'dd-MM-yyyy');
1055
1056
        $expiryValue = 'None';
1057
        if (!empty($this->ExpireAtDate)) {
0 ignored issues
show
Documentation introduced by
The property ExpireAtDate does not exist on object<DMSDocument>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
1058
            $expiryValue = 'Date';
1059
        }
1060
        $expiry = new OptionsetField(
1061
            'Expiry',
1062
            'Expiry',
1063
            array(
1064
                'None' => 'None',
1065
                'Date' => 'Set document to expire on'
1066
            ),
1067
            $expiryValue
1068
        );
1069
        $expiryDatetime = DatetimeField::create('ExpireAtDate', '');
1070
        $expiryDatetime->getDateField()
1071
            ->setConfig('showcalendar', true)
1072
            ->setConfig('dateformat', 'dd-MM-yyyy')
1073
            ->setConfig('datavalueformat', 'dd-MM-yyyy');
1074
1075
        // This adds all the actions details into a group.
1076
        // Embargo, History, etc to go in here
1077
        // These are toggled on and off via the Actions Buttons above
1078
        // exit('hit');
0 ignored issues
show
Unused Code Comprehensibility introduced by
84% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1079
        $actionsPanel = FieldGroup::create(
1080
            FieldGroup::create($embargo, $embargoDatetime)->addExtraClass('embargo'),
1081
            FieldGroup::create($expiry, $expiryDatetime)->addExtraClass('expiry'),
1082
            FieldGroup::create($uploadField)->addExtraClass('replace'),
1083
            FieldGroup::create($pagesGrid)->addExtraClass('find-usage'),
1084
            FieldGroup::create($referencesGrid)->addExtraClass('find-references'),
1085
            FieldGroup::create($versionsGrid)->addExtraClass('find-versions'),
0 ignored issues
show
Bug introduced by
The variable $versionsGrid does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1086
            FieldGroup::create($this->getRelatedDocumentsGridField())->addExtraClass('find-relateddocuments')
1087
        );
1088
1089
        $actionsPanel->setName("ActionsPanel");
1090
        $actionsPanel->addExtraClass("DMSDocumentActionsPanel");
1091
1092
        $fields->push($actionsPanel);
1093
1094
        $this->extend('updateCMSFields', $fields);
1095
1096
        return $fields;
1097
    }
1098
1099
    public function onBeforeWrite()
1100
    {
1101
        parent::onBeforeWrite();
1102
1103
        if (isset($this->Embargo)) {
1104
            //set the embargo options from the OptionSetField created in the getCMSFields method
1105
            //do not write after clearing the embargo (write happens automatically)
1106
            $savedDate = $this->EmbargoedUntilDate;
0 ignored issues
show
Documentation introduced by
The property EmbargoedUntilDate does not exist on object<DMSDocument>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
1107
            $this->clearEmbargo(false); //clear all previous settings and re-apply them on save
1108
1109
            if ($this->Embargo == 'Published') {
0 ignored issues
show
Documentation introduced by
The property Embargo does not exist on object<DMSDocument>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
1110
                $this->embargoUntilPublished(false);
1111
            }
1112
            if ($this->Embargo == 'Indefinitely') {
0 ignored issues
show
Documentation introduced by
The property Embargo does not exist on object<DMSDocument>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
1113
                $this->embargoIndefinitely(false);
1114
            }
1115
            if ($this->Embargo == 'Date') {
0 ignored issues
show
Documentation introduced by
The property Embargo does not exist on object<DMSDocument>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
1116
                $this->embargoUntilDate($savedDate, false);
1117
            }
1118
        }
1119
1120
        if (isset($this->Expiry)) {
1121
            if ($this->Expiry == 'Date') {
0 ignored issues
show
Documentation introduced by
The property Expiry does not exist on object<DMSDocument>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
1122
                $this->expireAtDate($this->ExpireAtDate, false);
0 ignored issues
show
Documentation introduced by
The property ExpireAtDate does not exist on object<DMSDocument>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
1123
            } else {
1124
                $this->clearExpiry(false);
1125
            } //clear all previous settings
1126
        }
1127
    }
1128
1129
    /**
1130
     * Return the relative URL of an icon for the file type, based on the
1131
     * {@link appCategory()} value.
1132
     *
1133
     * Images are searched for in "dms/images/app_icons/".
1134
     *
1135
     * @return string
1136
     */
1137
    public function Icon($ext)
1138
    {
1139
        if (!Director::fileExists(DMS_DIR."/images/app_icons/{$ext}_32.png")) {
1140
            $ext = File::get_app_category($ext);
1141
        }
1142
1143
        if (!Director::fileExists(DMS_DIR."/images/app_icons/{$ext}_32.png")) {
1144
            $ext = "generic";
1145
        }
1146
1147
        return DMS_DIR."/images/app_icons/{$ext}_32.png";
1148
    }
1149
1150
    /**
1151
     * Return the extension of the file associated with the document
1152
     *
1153
     * @return string
1154
     */
1155
    public function getExtension()
1156
    {
1157
        return strtolower(pathinfo($this->Filename, PATHINFO_EXTENSION));
0 ignored issues
show
Documentation introduced by
The property Filename does not exist on object<DMSDocument>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
1158
    }
1159
1160
    /**
1161
     * @return string
0 ignored issues
show
Documentation introduced by
Should the return type not be string|false?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
1162
     */
1163
    public function getSize()
1164
    {
1165
        $size = $this->getAbsoluteSize();
1166
        return ($size) ? File::format_size($size) : false;
1167
    }
1168
1169
    /**
1170
     * Return the size of the file associated with the document.
1171
     *
1172
     * @return string
0 ignored issues
show
Documentation introduced by
Should the return type not be integer|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
1173
     */
1174
    public function getAbsoluteSize()
1175
    {
1176
        return file_exists($this->getFullPath()) ? filesize($this->getFullPath()) : null;
1177
    }
1178
1179
    /**
1180
     * An alias to DMSDocument::getSize()
1181
     *
1182
     * @return string
0 ignored issues
show
Documentation introduced by
Should the return type not be string|false?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
1183
     */
1184
    public function getFileSizeFormatted()
1185
    {
1186
        return $this->getSize();
1187
    }
1188
1189
1190
    /**
1191
     * @return FieldList
0 ignored issues
show
Documentation introduced by
Should the return type not be FieldGroup?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
1192
     */
1193
    protected function getFieldsForFile($relationListCount)
1194
    {
1195
        $extension = $this->getExtension();
1196
1197
        $previewField = new LiteralField(
1198
            "ImageFull",
1199
            "<img id='thumbnailImage' class='thumbnail-preview' src='{$this->Icon($extension)}?r="
1200
            . rand(1, 100000) . "' alt='{$this->Title}' />\n"
0 ignored issues
show
Documentation introduced by
The property Title does not exist on object<DMSDocument>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
1201
        );
1202
1203
        //count the number of pages this document is published on
1204
        $publishedOnCount = $this->Pages()->Count();
1205
        $publishedOnValue = "$publishedOnCount pages";
1206
        if ($publishedOnCount == 1) {
1207
            $publishedOnValue = "$publishedOnCount page";
1208
        }
1209
1210
        $relationListCountValue = "$relationListCount pages";
1211
        if ($relationListCount == 1) {
1212
            $relationListCountValue = "$relationListCount page";
1213
        }
1214
1215
        $fields = new FieldGroup(
1216
            $filePreview = CompositeField::create(
1217
                CompositeField::create(
1218
                    $previewField
1219
                )->setName("FilePreviewImage")->addExtraClass('cms-file-info-preview'),
1220
                CompositeField::create(
1221
                    CompositeField::create(
1222
                        new ReadonlyField("ID", "ID number". ':', $this->ID),
1223
                        new ReadonlyField(
1224
                            "FileType",
1225
                            _t('AssetTableField.TYPE', 'File type') . ':',
1226
                            self::get_file_type($extension)
1227
                        ),
1228
                        new ReadonlyField(
1229
                            "Size",
1230
                            _t('AssetTableField.SIZE', 'File size') . ':',
1231
                            $this->getFileSizeFormatted()
1232
                        ),
1233
                        $urlField = new ReadonlyField(
1234
                            'ClickableURL',
1235
                            _t('AssetTableField.URL', 'URL'),
1236
                            sprintf(
1237
                                '<a href="%s" target="_blank" class="file-url">%s</a>',
1238
                                $this->getLink(),
1239
                                $this->getLink()
1240
                            )
1241
                        ),
1242
                        new ReadonlyField("FilenameWithoutIDField", "Filename". ':', $this->getFilenameWithoutID()),
1243
                        new DateField_Disabled(
1244
                            "Created",
1245
                            _t('AssetTableField.CREATED', 'First uploaded') . ':',
1246
                            $this->Created
1247
                        ),
1248
                        new DateField_Disabled(
1249
                            "LastEdited",
1250
                            _t('AssetTableField.LASTEDIT', 'Last changed') . ':',
1251
                            $this->LastEdited
1252
                        ),
1253
                        new DateField_Disabled(
1254
                            "LastChanged",
1255
                            _t('AssetTableField.LASTCHANGED', 'Last replaced') . ':',
1256
                            $this->LastChanged
0 ignored issues
show
Bug introduced by
The property LastChanged does not seem to exist. Did you mean changed?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
1257
                        ),
1258
                        new ReadonlyField("PublishedOn", "Published on". ':', $publishedOnValue),
1259
                        new ReadonlyField("ReferencedOn", "Referenced on". ':', $relationListCountValue),
1260
                        new ReadonlyField("ViewCount", "View count". ':', $this->ViewCount)
0 ignored issues
show
Documentation introduced by
The property ViewCount does not exist on object<DMSDocument>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
1261
                    )
1262
                )->setName("FilePreviewData")->addExtraClass('cms-file-info-data')
1263
            )->setName("FilePreview")->addExtraClass('cms-file-info')
1264
        );
1265
1266
        $fields->setName('FileP');
1267
        $urlField->dontEscape = true;
1268
1269
        return $fields;
1270
    }
1271
1272
    /**
1273
     * Takes a file and adds it to the DMSDocument storage, replacing the
1274
     * current file.
1275
     *
1276
     * @param File $file
1277
     *
1278
     * @return $this
1279
     */
1280
    public function ingestFile($file)
1281
    {
1282
        $this->replaceDocument($file);
1283
        $file->delete();
1284
1285
        return $this;
1286
    }
1287
1288
    /**
1289
     * Get a data list of documents related to this document
1290
     *
1291
     * @return DataList
1292
     */
1293
    public function getRelatedDocuments()
1294
    {
1295
        $documents = $this->RelatedDocuments();
0 ignored issues
show
Bug introduced by
The method RelatedDocuments() does not exist on DMSDocument. Did you maybe mean getRelatedDocuments()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
1296
1297
        $this->extend('updateRelatedDocuments', $documents);
1298
1299
        return $documents;
1300
    }
1301
1302
    /**
1303
     * Get a GridField for managing related documents
1304
     *
1305
     * @return GridField
1306
     */
1307
    protected function getRelatedDocumentsGridField()
1308
    {
1309
        $gridField = GridField::create(
1310
            'RelatedDocuments',
1311
            _t('DMSDocument.RELATEDDOCUMENTS', 'Related Documents'),
1312
            $this->RelatedDocuments(),
0 ignored issues
show
Bug introduced by
The method RelatedDocuments() does not exist on DMSDocument. Did you maybe mean getRelatedDocuments()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
1313
            new GridFieldConfig_RelationEditor
1314
        );
1315
1316
        $gridField->getConfig()->removeComponentsByType('GridFieldAddNewButton');
1317
        // Move the autocompleter to the left
1318
        $gridField->getConfig()->removeComponentsByType('GridFieldAddExistingAutocompleter');
1319
        $gridField->getConfig()->addComponent(new GridFieldAddExistingAutocompleter('buttons-before-left'));
1320
1321
        $this->extend('updateRelatedDocumentsGridField', $gridField);
1322
1323
        return $gridField;
1324
    }
1325
}
1326