|
1
|
|
|
<?php |
|
|
|
|
|
|
2
|
|
|
|
|
3
|
|
|
/** |
|
4
|
|
|
* @package dms |
|
5
|
|
|
* |
|
6
|
|
|
* @property Varchar Filename |
|
7
|
|
|
* @property Varchar Folder |
|
8
|
|
|
* @property Varchar Title |
|
9
|
|
|
* @property Text Description |
|
10
|
|
|
* @property int ViewCount |
|
11
|
|
|
* @property DateTime LastChanged |
|
12
|
|
|
* @property Boolean EmbargoedIndefinitely |
|
13
|
|
|
* @property Boolean EmbargoedUntilPublished |
|
14
|
|
|
* @property DateTime EmbargoedUntilDate |
|
15
|
|
|
* @property DateTime ExpireAtDate |
|
16
|
|
|
* @property Enum DownloadBehavior |
|
17
|
|
|
* @property Enum CanViewType Enum('Anyone, LoggedInUsers, OnlyTheseUsers', 'Anyone') |
|
18
|
|
|
* @property Enum CanEditType Enum('LoggedInUsers, OnlyTheseUsers', 'LoggedInUsers') |
|
19
|
|
|
* |
|
20
|
|
|
* @method ManyManyList RelatedDocuments |
|
21
|
|
|
* @method ManyManyList Tags |
|
22
|
|
|
* @method ManyManyList ViewerGroups |
|
23
|
|
|
* @method ManyManyList EditorGroups |
|
24
|
|
|
* |
|
25
|
|
|
*/ |
|
26
|
|
|
class DMSDocument extends DataObject implements DMSDocumentInterface |
|
|
|
|
|
|
27
|
|
|
{ |
|
28
|
|
|
private static $db = array( |
|
29
|
|
|
"Filename" => "Varchar(255)", // eg. 3469~2011-energysaving-report.pdf |
|
30
|
|
|
"Folder" => "Varchar(255)", // eg. 0 |
|
31
|
|
|
"Title" => 'Varchar(1024)', // eg. "Energy Saving Report for Year 2011, New Zealand LandCorp" |
|
32
|
|
|
"Description" => 'Text', |
|
33
|
|
|
"ViewCount" => 'Int', |
|
34
|
|
|
// When this document's file was created or last replaced (small changes like updating title don't count) |
|
35
|
|
|
"LastChanged" => 'SS_DateTime', |
|
36
|
|
|
|
|
37
|
|
|
"EmbargoedIndefinitely" => 'Boolean(false)', |
|
38
|
|
|
"EmbargoedUntilPublished" => 'Boolean(false)', |
|
39
|
|
|
"EmbargoedUntilDate" => 'SS_DateTime', |
|
40
|
|
|
"ExpireAtDate" => 'SS_DateTime', |
|
41
|
|
|
"DownloadBehavior" => 'Enum(array("open","download"), "download")', |
|
42
|
|
|
"CanViewType" => "Enum('Anyone, LoggedInUsers, OnlyTheseUsers', 'Anyone')", |
|
43
|
|
|
"CanEditType" => "Enum('LoggedInUsers, OnlyTheseUsers', 'LoggedInUsers')", |
|
44
|
|
|
); |
|
45
|
|
|
|
|
46
|
|
|
private static $many_many = array( |
|
47
|
|
|
'Pages' => 'SiteTree', |
|
48
|
|
|
'RelatedDocuments' => 'DMSDocument', |
|
49
|
|
|
'Tags' => 'DMSTag', |
|
50
|
|
|
'ViewerGroups' => 'Group', |
|
51
|
|
|
'EditorGroups' => 'Group', |
|
52
|
|
|
); |
|
53
|
|
|
|
|
54
|
|
|
private static $many_many_extraFields = array( |
|
55
|
|
|
'Pages' => array( |
|
56
|
|
|
'DocumentSort' => 'Int' |
|
57
|
|
|
) |
|
58
|
|
|
); |
|
59
|
|
|
|
|
60
|
|
|
private static $display_fields = array( |
|
61
|
|
|
'ID' => 'ID', |
|
62
|
|
|
'Title' => 'Title', |
|
63
|
|
|
'FilenameWithoutID' => 'Filename', |
|
64
|
|
|
'LastChanged' => 'LastChanged' |
|
65
|
|
|
); |
|
66
|
|
|
|
|
67
|
|
|
private static $singular_name = 'Document'; |
|
68
|
|
|
|
|
69
|
|
|
private static $plural_name = 'Documents'; |
|
70
|
|
|
|
|
71
|
|
|
private static $searchable_fields = array( |
|
72
|
|
|
'ID' => array( |
|
73
|
|
|
'filter' => 'ExactMatchFilter', |
|
74
|
|
|
'field' => 'NumericField' |
|
75
|
|
|
), |
|
76
|
|
|
'Title', |
|
77
|
|
|
'Filename', |
|
78
|
|
|
'LastChanged' |
|
79
|
|
|
); |
|
80
|
|
|
|
|
81
|
|
|
private static $summary_fields = array( |
|
82
|
|
|
'Filename' => 'Filename', |
|
83
|
|
|
'Title' => 'Title', |
|
84
|
|
|
'ViewCount' => 'ViewCount', |
|
85
|
|
|
'getPages.count' => 'Page Use' |
|
86
|
|
|
); |
|
87
|
|
|
|
|
88
|
|
|
/** |
|
89
|
|
|
* @var string download|open |
|
90
|
|
|
* @config |
|
91
|
|
|
*/ |
|
92
|
|
|
private static $default_download_behaviour = 'download'; |
|
93
|
|
|
|
|
94
|
|
|
public function canView($member = null) |
|
95
|
|
|
{ |
|
96
|
|
|
if (!$member || !(is_a($member, 'Member')) || is_numeric($member)) { |
|
97
|
|
|
$member = Member::currentUser(); |
|
98
|
|
|
} |
|
99
|
|
|
|
|
100
|
|
|
if (!$this->CanViewType || $this->CanViewType == 'Anyone') { |
|
101
|
|
|
return true; |
|
102
|
|
|
} |
|
103
|
|
|
|
|
104
|
|
|
if ($member && Permission::checkMember($member, |
|
105
|
|
|
array( |
|
106
|
|
|
'ADMIN', |
|
107
|
|
|
'SITETREE_EDIT_ALL', |
|
108
|
|
|
'SITETREE_VIEW_ALL', |
|
109
|
|
|
) |
|
110
|
|
|
) |
|
111
|
|
|
) { |
|
112
|
|
|
return true; |
|
113
|
|
|
} |
|
114
|
|
|
|
|
115
|
|
|
if ($this->isHidden()) { |
|
116
|
|
|
return false; |
|
117
|
|
|
} |
|
118
|
|
|
|
|
119
|
|
|
if ($this->CanViewType == 'LoggedInUsers') { |
|
120
|
|
|
return $member && $member->exists(); |
|
121
|
|
|
} |
|
122
|
|
|
|
|
123
|
|
|
if ($this->CanViewType == 'OnlyTheseUsers' && $this->ViewerGroups()->count()) { |
|
124
|
|
|
$result = ($member && $member->inGroups($this->ViewerGroups())); |
|
125
|
|
|
|
|
126
|
|
|
return $result; |
|
127
|
|
|
} |
|
128
|
|
|
|
|
129
|
|
|
return $this->canEdit($member); |
|
130
|
|
|
} |
|
131
|
|
|
|
|
132
|
|
|
public function canEdit($member = null) |
|
133
|
|
|
{ |
|
134
|
|
|
if (!$member || !(is_a($member, 'Member')) || is_numeric($member)) { |
|
135
|
|
|
$member = Member::currentUser(); |
|
136
|
|
|
} |
|
137
|
|
|
|
|
138
|
|
|
<<<<<<< HEAD |
|
|
|
|
|
|
139
|
|
|
======= |
|
140
|
|
|
if (!$this->CanEditType) { |
|
141
|
|
|
return false; |
|
142
|
|
|
} |
|
143
|
|
|
|
|
144
|
|
|
>>>>>>> 9947503a698163c85c0c3928496904aba5dbfb2b |
|
145
|
|
|
if ($this->CanEditType === 'LoggedInUsers') { |
|
146
|
|
|
return $member && $member->exists(); |
|
147
|
|
|
} |
|
148
|
|
|
if ($this->CanEditType === 'OnlyTheseUsers' && $this->EditorGroups()->count()) { |
|
149
|
|
|
return $member && $member->inGroups($this->EditorGroups()); |
|
150
|
|
|
} |
|
151
|
|
|
|
|
152
|
|
|
return ($member && Permission::checkMember($member, array('ADMIN', 'SITETREE_EDIT_ALL'))); |
|
153
|
|
|
} |
|
154
|
|
|
|
|
155
|
|
|
/** |
|
156
|
|
|
* @param Member $member |
|
157
|
|
|
* |
|
158
|
|
|
* @return boolean |
|
159
|
|
|
*/ |
|
160
|
|
|
public function canCreate($member = null) |
|
161
|
|
|
{ |
|
162
|
|
|
return $this->canEdit($member); |
|
163
|
|
|
} |
|
164
|
|
|
|
|
165
|
|
|
/** |
|
166
|
|
|
* @param Member $member |
|
167
|
|
|
* |
|
168
|
|
|
* @return boolean |
|
169
|
|
|
*/ |
|
170
|
|
|
public function canDelete($member = null) |
|
171
|
|
|
{ |
|
172
|
|
|
if (!$member || !(is_a($member, 'Member')) || is_numeric($member)) { |
|
173
|
|
|
$member = Member::currentUser(); |
|
174
|
|
|
} |
|
175
|
|
|
|
|
176
|
|
|
$results = $this->extend('canDelete', $member); |
|
177
|
|
|
|
|
178
|
|
|
if ($results && is_array($results)) { |
|
179
|
|
|
if (!min($results)) { |
|
180
|
|
|
return false; |
|
181
|
|
|
} |
|
182
|
|
|
} |
|
183
|
|
|
|
|
184
|
|
|
return $this->canView(); |
|
185
|
|
|
} |
|
186
|
|
|
|
|
187
|
|
|
|
|
188
|
|
|
|
|
189
|
|
|
/** |
|
190
|
|
|
* Associates this document with a Page. This method does nothing if the |
|
191
|
|
|
* association already exists. |
|
192
|
|
|
* |
|
193
|
|
|
* This could be a simple wrapper around $myDoc->Pages()->add($myPage) to |
|
194
|
|
|
* add a many_many relation. |
|
195
|
|
|
* |
|
196
|
|
|
* @param SiteTree $pageObject Page object to associate this Document with |
|
197
|
|
|
* |
|
198
|
|
|
* @return DMSDocument |
|
199
|
|
|
*/ |
|
200
|
|
|
public function addPage($pageObject) |
|
201
|
|
|
{ |
|
202
|
|
|
$this->Pages()->add($pageObject); |
|
203
|
|
|
|
|
204
|
|
|
DB::query( |
|
205
|
|
|
"UPDATE \"DMSDocument_Pages\" SET \"DocumentSort\"=\"DocumentSort\"+1" |
|
206
|
|
|
. " WHERE \"SiteTreeID\" = $pageObject->ID" |
|
207
|
|
|
); |
|
208
|
|
|
|
|
209
|
|
|
return $this; |
|
210
|
|
|
} |
|
211
|
|
|
|
|
212
|
|
|
/** |
|
213
|
|
|
* Associates this DMSDocument with a set of Pages. This method loops |
|
214
|
|
|
* through a set of page ids, and then associates this DMSDocument with the |
|
215
|
|
|
* individual Page with the each page id in the set. |
|
216
|
|
|
* |
|
217
|
|
|
* @param array $pageIDs |
|
218
|
|
|
* |
|
219
|
|
|
* @return DMSDocument |
|
220
|
|
|
*/ |
|
221
|
|
|
public function addPages($pageIDs) |
|
222
|
|
|
{ |
|
223
|
|
|
foreach ($pageIDs as $id) { |
|
224
|
|
|
$pageObject = DataObject::get_by_id("SiteTree", $id); |
|
225
|
|
|
|
|
226
|
|
|
if ($pageObject && $pageObject->exists()) { |
|
227
|
|
|
$this->addPage($pageObject); |
|
228
|
|
|
} |
|
229
|
|
|
} |
|
230
|
|
|
|
|
231
|
|
|
return $this; |
|
232
|
|
|
} |
|
233
|
|
|
|
|
234
|
|
|
/** |
|
235
|
|
|
* Removes the association between this Document and a Page. This method |
|
236
|
|
|
* does nothing if the association does not exist. |
|
237
|
|
|
* |
|
238
|
|
|
* @param SiteTree $pageObject Page object to remove the association to |
|
239
|
|
|
* |
|
240
|
|
|
* @return DMSDocument |
|
241
|
|
|
*/ |
|
242
|
|
|
public function removePage($pageObject) |
|
243
|
|
|
{ |
|
244
|
|
|
$this->Pages()->remove($pageObject); |
|
245
|
|
|
|
|
246
|
|
|
return $this; |
|
247
|
|
|
} |
|
248
|
|
|
|
|
249
|
|
|
/** |
|
250
|
|
|
* @see getPages() |
|
251
|
|
|
* |
|
252
|
|
|
* @return DataList |
|
253
|
|
|
*/ |
|
254
|
|
|
public function Pages() |
|
255
|
|
|
{ |
|
256
|
|
|
$pages = $this->getManyManyComponents('Pages'); |
|
257
|
|
|
$this->extend('updatePages', $pages); |
|
258
|
|
|
|
|
259
|
|
|
return $pages; |
|
260
|
|
|
} |
|
261
|
|
|
|
|
262
|
|
|
/** |
|
263
|
|
|
* Returns a list of the Page objects associated with this Document. |
|
264
|
|
|
* |
|
265
|
|
|
* @return DataList |
|
266
|
|
|
*/ |
|
267
|
|
|
public function getPages() |
|
268
|
|
|
{ |
|
269
|
|
|
return $this->Pages(); |
|
270
|
|
|
} |
|
271
|
|
|
|
|
272
|
|
|
/** |
|
273
|
|
|
* Removes all associated Pages from the DMSDocument |
|
274
|
|
|
* |
|
275
|
|
|
* @return DMSDocument |
|
276
|
|
|
*/ |
|
277
|
|
|
public function removeAllPages() |
|
278
|
|
|
{ |
|
279
|
|
|
$this->Pages()->removeAll(); |
|
280
|
|
|
|
|
281
|
|
|
return $this; |
|
282
|
|
|
} |
|
283
|
|
|
|
|
284
|
|
|
/** |
|
285
|
|
|
* Increase ViewCount by 1, without update any other record fields such as |
|
286
|
|
|
* LastEdited. |
|
287
|
|
|
* |
|
288
|
|
|
* @return DMSDocument |
|
289
|
|
|
*/ |
|
290
|
|
|
public function trackView() |
|
291
|
|
|
{ |
|
292
|
|
|
if ($this->ID > 0) { |
|
293
|
|
|
$count = $this->ViewCount + 1; |
|
294
|
|
|
|
|
295
|
|
|
$this->ViewCount = $count; |
|
296
|
|
|
|
|
297
|
|
|
DB::query("UPDATE \"DMSDocument\" SET \"ViewCount\"='$count' WHERE \"ID\"={$this->ID}"); |
|
298
|
|
|
} |
|
299
|
|
|
|
|
300
|
|
|
return $this; |
|
301
|
|
|
} |
|
302
|
|
|
|
|
303
|
|
|
|
|
304
|
|
|
/** |
|
305
|
|
|
* Adds a metadata tag to the Document. The tag has a category and a value. |
|
306
|
|
|
* |
|
307
|
|
|
* Each category can have multiple values by default. So: |
|
308
|
|
|
* addTag("fruit","banana") addTag("fruit", "apple") will add two items. |
|
309
|
|
|
* |
|
310
|
|
|
* However, if the third parameter $multiValue is set to 'false', then all |
|
311
|
|
|
* updates to a category only ever update a single value. So: |
|
312
|
|
|
* addTag("fruit","banana") addTag("fruit", "apple") would result in a |
|
313
|
|
|
* single metadata tag: fruit->apple. |
|
314
|
|
|
* |
|
315
|
|
|
* Can could be implemented as a key/value store table (although it is more |
|
316
|
|
|
* like category/value, because the same category can occur multiple times) |
|
317
|
|
|
* |
|
318
|
|
|
* @param string $category of a metadata category to add (required) |
|
319
|
|
|
* @param string $value of a metadata value to add (required) |
|
320
|
|
|
* @param bool $multiValue Boolean that determines if the category is |
|
321
|
|
|
* multi-value or single-value (optional) |
|
322
|
|
|
* |
|
323
|
|
|
* @return DMSDocument |
|
324
|
|
|
*/ |
|
325
|
|
|
public function addTag($category, $value, $multiValue = true) |
|
326
|
|
|
{ |
|
327
|
|
|
if ($multiValue) { |
|
328
|
|
|
//check for a duplicate tag, don't add the duplicate |
|
329
|
|
|
$currentTag = $this->Tags()->filter(array('Category' => $category, 'Value' => $value)); |
|
330
|
|
|
if ($currentTag->Count() == 0) { |
|
331
|
|
|
//multi value tag |
|
332
|
|
|
$tag = new DMSTag(); |
|
333
|
|
|
$tag->Category = $category; |
|
334
|
|
|
$tag->Value = $value; |
|
335
|
|
|
$tag->MultiValue = true; |
|
336
|
|
|
$tag->write(); |
|
337
|
|
|
$tag->Documents()->add($this); |
|
338
|
|
|
} else { |
|
339
|
|
|
//add the relation between the tag and document |
|
340
|
|
|
foreach ($currentTag as $tagObj) { |
|
341
|
|
|
$tagObj->Documents()->add($this); |
|
342
|
|
|
} |
|
343
|
|
|
} |
|
344
|
|
|
} else { |
|
345
|
|
|
//single value tag |
|
346
|
|
|
$currentTag = $this->Tags()->filter(array('Category' => $category)); |
|
347
|
|
|
$tag = null; |
|
348
|
|
|
if ($currentTag->Count() == 0) { |
|
349
|
|
|
//create the single-value tag |
|
350
|
|
|
$tag = new DMSTag(); |
|
351
|
|
|
$tag->Category = $category; |
|
352
|
|
|
$tag->Value = $value; |
|
353
|
|
|
$tag->MultiValue = false; |
|
354
|
|
|
$tag->write(); |
|
355
|
|
|
} else { |
|
356
|
|
|
//update the single value tag |
|
357
|
|
|
$tag = $currentTag->first(); |
|
358
|
|
|
$tag->Value = $value; |
|
359
|
|
|
$tag->MultiValue = false; |
|
360
|
|
|
$tag->write(); |
|
361
|
|
|
} |
|
362
|
|
|
|
|
363
|
|
|
// regardless of whether we created a new tag or are just updating an |
|
364
|
|
|
// existing one, add the relation |
|
365
|
|
|
$tag->Documents()->add($this); |
|
366
|
|
|
} |
|
367
|
|
|
|
|
368
|
|
|
return $this; |
|
369
|
|
|
} |
|
370
|
|
|
|
|
371
|
|
|
/** |
|
372
|
|
|
* @param string $category |
|
373
|
|
|
* @param string $value |
|
374
|
|
|
* |
|
375
|
|
|
* @return DataList |
|
376
|
|
|
*/ |
|
377
|
|
|
protected function getTagsObjects($category, $value = null) |
|
378
|
|
|
{ |
|
379
|
|
|
$valueFilter = array("Category" => $category); |
|
380
|
|
|
if (!empty($value)) { |
|
381
|
|
|
$valueFilter['Value'] = $value; |
|
382
|
|
|
} |
|
383
|
|
|
|
|
384
|
|
|
$tags = $this->Tags()->filter($valueFilter); |
|
385
|
|
|
return $tags; |
|
386
|
|
|
} |
|
387
|
|
|
|
|
388
|
|
|
/** |
|
389
|
|
|
* Fetches all tags associated with this DMSDocument within a given |
|
390
|
|
|
* category. If a value is specified this method tries to fetch that |
|
391
|
|
|
* specific tag. |
|
392
|
|
|
* |
|
393
|
|
|
* @param string $category metadata category to get |
|
394
|
|
|
* @param string $value value of the tag to get |
|
395
|
|
|
* |
|
396
|
|
|
* @return array Strings of all the tags or null if there is no match found |
|
397
|
|
|
*/ |
|
398
|
|
|
public function getTagsList($category, $value = null) |
|
399
|
|
|
{ |
|
400
|
|
|
$tags = $this->getTagsObjects($category, $value); |
|
401
|
|
|
|
|
402
|
|
|
$returnArray = null; |
|
403
|
|
|
|
|
404
|
|
|
if ($tags->Count() > 0) { |
|
405
|
|
|
$returnArray = array(); |
|
406
|
|
|
|
|
407
|
|
|
foreach ($tags as $t) { |
|
408
|
|
|
$returnArray[] = $t->Value; |
|
409
|
|
|
} |
|
410
|
|
|
} |
|
411
|
|
|
|
|
412
|
|
|
return $returnArray; |
|
413
|
|
|
} |
|
414
|
|
|
|
|
415
|
|
|
/** |
|
416
|
|
|
* Removes a tag from the Document. If you only set a category, then all |
|
417
|
|
|
* values in that category are deleted. |
|
418
|
|
|
* |
|
419
|
|
|
* If you specify both a category and a value, then only that single |
|
420
|
|
|
* category/value pair is deleted. |
|
421
|
|
|
* |
|
422
|
|
|
* Nothing happens if the category or the value do not exist. |
|
423
|
|
|
* |
|
424
|
|
|
* @param string $category Category to remove |
|
425
|
|
|
* @param string $value Value to remove |
|
426
|
|
|
* |
|
427
|
|
|
* @return DMSDocument |
|
428
|
|
|
*/ |
|
429
|
|
|
public function removeTag($category, $value = null) |
|
430
|
|
|
{ |
|
431
|
|
|
$tags = $this->getTagsObjects($category, $value); |
|
432
|
|
|
|
|
433
|
|
|
if ($tags->Count() > 0) { |
|
434
|
|
|
foreach ($tags as $t) { |
|
435
|
|
|
$documentList = $t->Documents(); |
|
436
|
|
|
|
|
437
|
|
|
//remove the relation between the tag and the document |
|
438
|
|
|
$documentList->remove($this); |
|
439
|
|
|
|
|
440
|
|
|
//delete the entire tag if it has no relations left |
|
441
|
|
|
if ($documentList->Count() == 0) { |
|
442
|
|
|
$t->delete(); |
|
443
|
|
|
} |
|
444
|
|
|
} |
|
445
|
|
|
} |
|
446
|
|
|
|
|
447
|
|
|
return $this; |
|
448
|
|
|
} |
|
449
|
|
|
|
|
450
|
|
|
/** |
|
451
|
|
|
* Deletes all tags associated with this Document. |
|
452
|
|
|
* |
|
453
|
|
|
* @return DMSDocument |
|
454
|
|
|
*/ |
|
455
|
|
|
public function removeAllTags() |
|
456
|
|
|
{ |
|
457
|
|
|
$allTags = $this->Tags(); |
|
458
|
|
|
|
|
459
|
|
|
foreach ($allTags as $tag) { |
|
460
|
|
|
$documentlist = $tag->Documents(); |
|
461
|
|
|
$documentlist->remove($this); |
|
462
|
|
|
if ($tag->Documents()->Count() == 0) { |
|
463
|
|
|
$tag->delete(); |
|
464
|
|
|
} |
|
465
|
|
|
} |
|
466
|
|
|
|
|
467
|
|
|
return $this; |
|
468
|
|
|
} |
|
469
|
|
|
|
|
470
|
|
|
/** |
|
471
|
|
|
* Returns a link to download this document from the DMS store. |
|
472
|
|
|
* |
|
473
|
|
|
* @return string |
|
474
|
|
|
*/ |
|
475
|
|
|
public function getLink() |
|
476
|
|
|
{ |
|
477
|
|
|
return Controller::join_links(Director::baseURL(), 'dmsdocument/'.$this->ID); |
|
478
|
|
|
} |
|
479
|
|
|
|
|
480
|
|
|
/** |
|
481
|
|
|
* @return string |
|
482
|
|
|
*/ |
|
483
|
|
|
public function Link() |
|
484
|
|
|
{ |
|
485
|
|
|
return $this->getLink(); |
|
486
|
|
|
} |
|
487
|
|
|
|
|
488
|
|
|
/** |
|
489
|
|
|
* Hides the document, so it does not show up when getByPage($myPage) is |
|
490
|
|
|
* called (without specifying the $showEmbargoed = true parameter). |
|
491
|
|
|
* |
|
492
|
|
|
* This is similar to expire, except that this method should be used to hide |
|
493
|
|
|
* documents that have not yet gone live. |
|
494
|
|
|
* |
|
495
|
|
|
* @param bool $write Save change to the database |
|
496
|
|
|
* |
|
497
|
|
|
* @return DMSDocument |
|
498
|
|
|
*/ |
|
499
|
|
|
public function embargoIndefinitely($write = true) |
|
500
|
|
|
{ |
|
501
|
|
|
$this->EmbargoedIndefinitely = true; |
|
502
|
|
|
|
|
503
|
|
|
if ($write) { |
|
504
|
|
|
$this->write(); |
|
505
|
|
|
} |
|
506
|
|
|
|
|
507
|
|
|
return $this; |
|
508
|
|
|
} |
|
509
|
|
|
|
|
510
|
|
|
/** |
|
511
|
|
|
* Hides the document until any page it is linked to is published |
|
512
|
|
|
* |
|
513
|
|
|
* @param bool $write Save change to database |
|
514
|
|
|
* |
|
515
|
|
|
* @return DMSDocument |
|
516
|
|
|
*/ |
|
517
|
|
|
public function embargoUntilPublished($write = true) |
|
518
|
|
|
{ |
|
519
|
|
|
$this->EmbargoedUntilPublished = true; |
|
520
|
|
|
|
|
521
|
|
|
if ($write) { |
|
522
|
|
|
$this->write(); |
|
523
|
|
|
} |
|
524
|
|
|
|
|
525
|
|
|
return $this; |
|
526
|
|
|
} |
|
527
|
|
|
|
|
528
|
|
|
/** |
|
529
|
|
|
* Returns if this is Document is embargoed or expired. |
|
530
|
|
|
* |
|
531
|
|
|
* Also, returns if the document should be displayed on the front-end, |
|
532
|
|
|
* respecting the current reading mode of the site and the embargo status. |
|
533
|
|
|
* |
|
534
|
|
|
* I.e. if a document is embargoed until published, then it should still |
|
535
|
|
|
* show up in draft mode. |
|
536
|
|
|
* |
|
537
|
|
|
* @return bool |
|
538
|
|
|
*/ |
|
539
|
|
|
public function isHidden() |
|
540
|
|
|
{ |
|
541
|
|
|
$hidden = $this->isEmbargoed() || $this->isExpired(); |
|
542
|
|
|
$readingMode = Versioned::get_reading_mode(); |
|
543
|
|
|
|
|
544
|
|
|
if ($readingMode == "Stage.Stage") { |
|
545
|
|
|
if ($this->EmbargoedUntilPublished == true) { |
|
546
|
|
|
$hidden = false; |
|
547
|
|
|
} |
|
548
|
|
|
} |
|
549
|
|
|
|
|
550
|
|
|
return $hidden; |
|
551
|
|
|
} |
|
552
|
|
|
|
|
553
|
|
|
/** |
|
554
|
|
|
* Returns if this is Document is embargoed. |
|
555
|
|
|
* |
|
556
|
|
|
* @return bool |
|
557
|
|
|
*/ |
|
558
|
|
|
public function isEmbargoed() |
|
559
|
|
|
{ |
|
560
|
|
|
if (is_object($this->EmbargoedUntilDate)) { |
|
561
|
|
|
$this->EmbargoedUntilDate = $this->EmbargoedUntilDate->Value; |
|
562
|
|
|
} |
|
563
|
|
|
|
|
564
|
|
|
$embargoed = false; |
|
565
|
|
|
|
|
566
|
|
|
if ($this->EmbargoedIndefinitely) { |
|
567
|
|
|
$embargoed = true; |
|
568
|
|
|
} elseif ($this->EmbargoedUntilPublished) { |
|
569
|
|
|
$embargoed = true; |
|
570
|
|
|
} elseif (!empty($this->EmbargoedUntilDate)) { |
|
571
|
|
|
if (SS_Datetime::now()->Value < $this->EmbargoedUntilDate) { |
|
572
|
|
|
$embargoed = true; |
|
573
|
|
|
} |
|
574
|
|
|
} |
|
575
|
|
|
|
|
576
|
|
|
return $embargoed; |
|
577
|
|
|
} |
|
578
|
|
|
|
|
579
|
|
|
/** |
|
580
|
|
|
* Hides the document, so it does not show up when getByPage($myPage) is |
|
581
|
|
|
* called. Automatically un-hides the Document at a specific date. |
|
582
|
|
|
* |
|
583
|
|
|
* @param string $datetime date time value when this Document should expire. |
|
584
|
|
|
* @param bool $write |
|
585
|
|
|
* |
|
586
|
|
|
* @return DMSDocument |
|
587
|
|
|
*/ |
|
588
|
|
|
public function embargoUntilDate($datetime, $write = true) |
|
589
|
|
|
{ |
|
590
|
|
|
$this->EmbargoedUntilDate = DBField::create_field('SS_Datetime', $datetime)->Format('Y-m-d H:i:s'); |
|
591
|
|
|
|
|
592
|
|
|
if ($write) { |
|
593
|
|
|
$this->write(); |
|
594
|
|
|
} |
|
595
|
|
|
|
|
596
|
|
|
return $this; |
|
597
|
|
|
} |
|
598
|
|
|
|
|
599
|
|
|
/** |
|
600
|
|
|
* Clears any previously set embargos, so the Document always shows up in |
|
601
|
|
|
* all queries. |
|
602
|
|
|
* |
|
603
|
|
|
* @param bool $write |
|
604
|
|
|
* |
|
605
|
|
|
* @return DMSDocument |
|
606
|
|
|
*/ |
|
607
|
|
|
public function clearEmbargo($write = true) |
|
608
|
|
|
{ |
|
609
|
|
|
$this->EmbargoedIndefinitely = false; |
|
610
|
|
|
$this->EmbargoedUntilPublished = false; |
|
611
|
|
|
$this->EmbargoedUntilDate = null; |
|
612
|
|
|
|
|
613
|
|
|
if ($write) { |
|
614
|
|
|
$this->write(); |
|
615
|
|
|
} |
|
616
|
|
|
|
|
617
|
|
|
return $this; |
|
618
|
|
|
} |
|
619
|
|
|
|
|
620
|
|
|
/** |
|
621
|
|
|
* Returns if this is Document is expired. |
|
622
|
|
|
* |
|
623
|
|
|
* @return bool |
|
624
|
|
|
*/ |
|
625
|
|
|
public function isExpired() |
|
626
|
|
|
{ |
|
627
|
|
|
if (is_object($this->ExpireAtDate)) { |
|
628
|
|
|
$this->ExpireAtDate = $this->ExpireAtDate->Value; |
|
629
|
|
|
} |
|
630
|
|
|
|
|
631
|
|
|
$expired = false; |
|
632
|
|
|
|
|
633
|
|
|
if (!empty($this->ExpireAtDate)) { |
|
634
|
|
|
if (SS_Datetime::now()->Value >= $this->ExpireAtDate) { |
|
635
|
|
|
$expired = true; |
|
636
|
|
|
} |
|
637
|
|
|
} |
|
638
|
|
|
|
|
639
|
|
|
return $expired; |
|
640
|
|
|
} |
|
641
|
|
|
|
|
642
|
|
|
/** |
|
643
|
|
|
* Hides the document at a specific date, so it does not show up when |
|
644
|
|
|
* getByPage($myPage) is called. |
|
645
|
|
|
* |
|
646
|
|
|
* @param string $datetime date time value when this Document should expire |
|
647
|
|
|
* @param bool $write |
|
648
|
|
|
* |
|
649
|
|
|
* @return DMSDocument |
|
650
|
|
|
*/ |
|
651
|
|
|
public function expireAtDate($datetime, $write = true) |
|
652
|
|
|
{ |
|
653
|
|
|
$this->ExpireAtDate = DBField::create_field('SS_Datetime', $datetime)->Format('Y-m-d H:i:s'); |
|
654
|
|
|
|
|
655
|
|
|
if ($write) { |
|
656
|
|
|
$this->write(); |
|
657
|
|
|
} |
|
658
|
|
|
|
|
659
|
|
|
return $this; |
|
660
|
|
|
} |
|
661
|
|
|
|
|
662
|
|
|
/** |
|
663
|
|
|
* Clears any previously set expiry. |
|
664
|
|
|
* |
|
665
|
|
|
* @param bool $write |
|
666
|
|
|
* |
|
667
|
|
|
* @return DMSDocument |
|
668
|
|
|
*/ |
|
669
|
|
|
public function clearExpiry($write = true) |
|
670
|
|
|
{ |
|
671
|
|
|
$this->ExpireAtDate = null; |
|
672
|
|
|
|
|
673
|
|
|
if ($write) { |
|
674
|
|
|
$this->write(); |
|
675
|
|
|
} |
|
676
|
|
|
|
|
677
|
|
|
return $this; |
|
678
|
|
|
} |
|
679
|
|
|
|
|
680
|
|
|
/** |
|
681
|
|
|
* Returns a DataList of all previous Versions of this document (check the |
|
682
|
|
|
* LastEdited date of each object to find the correct one). |
|
683
|
|
|
* |
|
684
|
|
|
* If {@link DMSDocument_versions::$enable_versions} is disabled then an |
|
685
|
|
|
* Exception is thrown |
|
686
|
|
|
* |
|
687
|
|
|
* @throws Exception |
|
688
|
|
|
* |
|
689
|
|
|
* @return DataList List of Document objects |
|
690
|
|
|
*/ |
|
691
|
|
|
public function getVersions() |
|
692
|
|
|
{ |
|
693
|
|
|
if (!DMSDocument_versions::$enable_versions) { |
|
694
|
|
|
throw new Exception("DMSDocument versions are disabled"); |
|
695
|
|
|
} |
|
696
|
|
|
|
|
697
|
|
|
return DMSDocument_versions::get_versions($this); |
|
698
|
|
|
} |
|
699
|
|
|
|
|
700
|
|
|
/** |
|
701
|
|
|
* Returns the full filename of the document stored in this object. |
|
702
|
|
|
* |
|
703
|
|
|
* @return string |
|
704
|
|
|
*/ |
|
705
|
|
|
public function getFullPath() |
|
706
|
|
|
{ |
|
707
|
|
|
if ($this->Filename) { |
|
708
|
|
|
return DMS::get_dms_path() . DIRECTORY_SEPARATOR . $this->Folder . DIRECTORY_SEPARATOR . $this->Filename; |
|
709
|
|
|
} |
|
710
|
|
|
|
|
711
|
|
|
return null; |
|
712
|
|
|
} |
|
713
|
|
|
|
|
714
|
|
|
/** |
|
715
|
|
|
* Returns the filename of this asset. |
|
716
|
|
|
* |
|
717
|
|
|
* @return string |
|
718
|
|
|
*/ |
|
719
|
|
|
public function getFileName() |
|
720
|
|
|
{ |
|
721
|
|
|
if ($this->getField('Filename')) { |
|
722
|
|
|
return $this->getField('Filename'); |
|
723
|
|
|
} else { |
|
724
|
|
|
return ASSETS_DIR . '/'; |
|
725
|
|
|
} |
|
726
|
|
|
} |
|
727
|
|
|
|
|
728
|
|
|
/** |
|
729
|
|
|
* @return string |
|
730
|
|
|
*/ |
|
731
|
|
|
public function getName() |
|
732
|
|
|
{ |
|
733
|
|
|
return $this->getField('Title'); |
|
734
|
|
|
} |
|
735
|
|
|
|
|
736
|
|
|
|
|
737
|
|
|
/** |
|
738
|
|
|
* @return string |
|
739
|
|
|
*/ |
|
740
|
|
|
public function getFilenameWithoutID() |
|
741
|
|
|
{ |
|
742
|
|
|
$filenameParts = explode('~', $this->Filename); |
|
743
|
|
|
$filename = array_pop($filenameParts); |
|
744
|
|
|
|
|
745
|
|
|
return $filename; |
|
746
|
|
|
} |
|
747
|
|
|
|
|
748
|
|
|
/** |
|
749
|
|
|
* @return string |
|
750
|
|
|
*/ |
|
751
|
|
|
public function getStorageFolder() |
|
752
|
|
|
{ |
|
753
|
|
|
return DMS::get_dms_path() . DIRECTORY_SEPARATOR . DMS::get_storage_folder($this->ID); |
|
754
|
|
|
} |
|
755
|
|
|
|
|
756
|
|
|
/** |
|
757
|
|
|
* Deletes the DMSDocument, its underlying file, as well as any tags related |
|
758
|
|
|
* to this DMSDocument. Also calls the parent DataObject's delete method in |
|
759
|
|
|
* order to complete an cascade. |
|
760
|
|
|
* |
|
761
|
|
|
* @return void |
|
762
|
|
|
*/ |
|
763
|
|
|
public function delete() |
|
764
|
|
|
{ |
|
765
|
|
|
// remove tags |
|
766
|
|
|
$this->removeAllTags(); |
|
767
|
|
|
|
|
768
|
|
|
// delete the file (and previous versions of files) |
|
769
|
|
|
$filesToDelete = array(); |
|
770
|
|
|
$storageFolder = $this->getStorageFolder(); |
|
771
|
|
|
|
|
772
|
|
|
if (file_exists($storageFolder)) { |
|
773
|
|
|
if ($handle = opendir($storageFolder)) { |
|
774
|
|
|
while (false !== ($entry = readdir($handle))) { |
|
775
|
|
|
// only delete if filename starts the the relevant ID |
|
776
|
|
|
if (strpos($entry, $this->ID.'~') === 0) { |
|
777
|
|
|
$filesToDelete[] = $entry; |
|
778
|
|
|
} |
|
779
|
|
|
} |
|
780
|
|
|
|
|
781
|
|
|
closedir($handle); |
|
782
|
|
|
|
|
783
|
|
|
//delete all this files that have the id of this document |
|
784
|
|
|
foreach ($filesToDelete as $file) { |
|
785
|
|
|
$filePath = $storageFolder .DIRECTORY_SEPARATOR . $file; |
|
786
|
|
|
|
|
787
|
|
|
if (is_file($filePath)) { |
|
788
|
|
|
unlink($filePath); |
|
789
|
|
|
} |
|
790
|
|
|
} |
|
791
|
|
|
} |
|
792
|
|
|
} |
|
793
|
|
|
|
|
794
|
|
|
$this->removeAllPages(); |
|
795
|
|
|
|
|
796
|
|
|
// get rid of any versions have saved for this DMSDocument, too |
|
797
|
|
|
if (DMSDocument_versions::$enable_versions) { |
|
798
|
|
|
$versions = $this->getVersions(); |
|
799
|
|
|
|
|
800
|
|
|
if ($versions->Count() > 0) { |
|
801
|
|
|
foreach ($versions as $v) { |
|
802
|
|
|
$v->delete(); |
|
803
|
|
|
} |
|
804
|
|
|
} |
|
805
|
|
|
} |
|
806
|
|
|
|
|
807
|
|
|
parent::delete(); |
|
808
|
|
|
} |
|
809
|
|
|
|
|
810
|
|
|
|
|
811
|
|
|
|
|
812
|
|
|
/** |
|
813
|
|
|
* Relate an existing file on the filesystem to the document. |
|
814
|
|
|
* |
|
815
|
|
|
* Copies the file to the new destination, as defined in {@link get_DMS_path()}. |
|
816
|
|
|
* |
|
817
|
|
|
* @param string $filePath Path to file, relative to webroot. |
|
818
|
|
|
* |
|
819
|
|
|
* @return DMSDocument |
|
820
|
|
|
*/ |
|
821
|
|
|
public function storeDocument($filePath) |
|
822
|
|
|
{ |
|
823
|
|
|
if (empty($this->ID)) { |
|
824
|
|
|
user_error("Document must be written to database before it can store documents", E_USER_ERROR); |
|
825
|
|
|
} |
|
826
|
|
|
|
|
827
|
|
|
// calculate all the path to copy the file to |
|
828
|
|
|
$fromFilename = basename($filePath); |
|
829
|
|
|
$toFilename = $this->ID. '~' . $fromFilename; //add the docID to the start of the Filename |
|
830
|
|
|
$toFolder = DMS::get_storage_folder($this->ID); |
|
831
|
|
|
$toPath = DMS::get_dms_path() . DIRECTORY_SEPARATOR . $toFolder . DIRECTORY_SEPARATOR . $toFilename; |
|
832
|
|
|
|
|
833
|
|
|
DMS::create_storage_folder(DMS::get_dms_path() . DIRECTORY_SEPARATOR . $toFolder); |
|
834
|
|
|
|
|
835
|
|
|
//copy the file into place |
|
836
|
|
|
$fromPath = BASE_PATH . DIRECTORY_SEPARATOR . $filePath; |
|
837
|
|
|
|
|
838
|
|
|
//version the existing file (copy it to a new "very specific" filename |
|
839
|
|
|
if (DMSDocument_versions::$enable_versions) { |
|
840
|
|
|
DMSDocument_versions::create_version($this); |
|
841
|
|
|
} else { //otherwise delete the old document file |
|
842
|
|
|
$oldPath = $this->getFullPath(); |
|
843
|
|
|
if (file_exists($oldPath)) { |
|
844
|
|
|
unlink($oldPath); |
|
845
|
|
|
} |
|
846
|
|
|
} |
|
847
|
|
|
|
|
848
|
|
|
copy($fromPath, $toPath); //this will overwrite the existing file (if present) |
|
849
|
|
|
|
|
850
|
|
|
//write the filename of the stored document |
|
851
|
|
|
$this->Filename = $toFilename; |
|
852
|
|
|
$this->Folder = strval($toFolder); |
|
853
|
|
|
|
|
854
|
|
|
$extension = pathinfo($this->Filename, PATHINFO_EXTENSION); |
|
855
|
|
|
|
|
856
|
|
|
if (empty($this->Title)) { |
|
857
|
|
|
// don't overwrite existing document titles |
|
858
|
|
|
$this->Title = basename($filePath, '.'.$extension); |
|
859
|
|
|
} |
|
860
|
|
|
|
|
861
|
|
|
$this->LastChanged = SS_Datetime::now()->Rfc2822(); |
|
862
|
|
|
$this->write(); |
|
863
|
|
|
|
|
864
|
|
|
return $this; |
|
865
|
|
|
} |
|
866
|
|
|
|
|
867
|
|
|
/** |
|
868
|
|
|
* Takes a File object or a String (path to a file) and copies it into the |
|
869
|
|
|
* DMS, replacing the original document file but keeping the rest of the |
|
870
|
|
|
* document unchanged. |
|
871
|
|
|
* |
|
872
|
|
|
* @param File|string $file path to a file to store |
|
873
|
|
|
* |
|
874
|
|
|
* @return DMSDocument object that we replaced the file in |
|
875
|
|
|
*/ |
|
876
|
|
|
public function replaceDocument($file) |
|
877
|
|
|
{ |
|
878
|
|
|
$filePath = DMS::transform_file_to_file_path($file); |
|
879
|
|
|
$doc = $this->storeDocument($filePath); // replace the document |
|
880
|
|
|
|
|
881
|
|
|
return $doc; |
|
882
|
|
|
} |
|
883
|
|
|
|
|
884
|
|
|
|
|
885
|
|
|
/** |
|
886
|
|
|
* Return the type of file for the given extension |
|
887
|
|
|
* on the current file name. |
|
888
|
|
|
* |
|
889
|
|
|
* @param string $ext |
|
890
|
|
|
* |
|
891
|
|
|
* @return string |
|
892
|
|
|
*/ |
|
893
|
|
|
public static function get_file_type($ext) |
|
894
|
|
|
{ |
|
895
|
|
|
$types = array( |
|
896
|
|
|
'gif' => 'GIF image - good for diagrams', |
|
897
|
|
|
'jpg' => 'JPEG image - good for photos', |
|
898
|
|
|
'jpeg' => 'JPEG image - good for photos', |
|
899
|
|
|
'png' => 'PNG image - good general-purpose format', |
|
900
|
|
|
'ico' => 'Icon image', |
|
901
|
|
|
'tiff' => 'Tagged image format', |
|
902
|
|
|
'doc' => 'Word document', |
|
903
|
|
|
'xls' => 'Excel spreadsheet', |
|
904
|
|
|
'zip' => 'ZIP compressed file', |
|
905
|
|
|
'gz' => 'GZIP compressed file', |
|
906
|
|
|
'dmg' => 'Apple disk image', |
|
907
|
|
|
'pdf' => 'Adobe Acrobat PDF file', |
|
908
|
|
|
'mp3' => 'MP3 audio file', |
|
909
|
|
|
'wav' => 'WAV audo file', |
|
910
|
|
|
'avi' => 'AVI video file', |
|
911
|
|
|
'mpg' => 'MPEG video file', |
|
912
|
|
|
'mpeg' => 'MPEG video file', |
|
913
|
|
|
'js' => 'Javascript file', |
|
914
|
|
|
'css' => 'CSS file', |
|
915
|
|
|
'html' => 'HTML file', |
|
916
|
|
|
'htm' => 'HTML file' |
|
917
|
|
|
); |
|
918
|
|
|
|
|
919
|
|
|
return isset($types[$ext]) ? $types[$ext] : $ext; |
|
920
|
|
|
} |
|
921
|
|
|
|
|
922
|
|
|
|
|
923
|
|
|
/** |
|
924
|
|
|
* Returns the Description field with HTML <br> tags added when there is a |
|
925
|
|
|
* line break. |
|
926
|
|
|
* |
|
927
|
|
|
* @return string |
|
928
|
|
|
*/ |
|
929
|
|
|
public function getDescriptionWithLineBreak() |
|
930
|
|
|
{ |
|
931
|
|
|
return nl2br($this->getField('Description')); |
|
932
|
|
|
} |
|
933
|
|
|
|
|
934
|
|
|
/** |
|
935
|
|
|
* @return FieldList |
|
936
|
|
|
*/ |
|
937
|
|
|
public function getCMSFields() |
|
938
|
|
|
{ |
|
939
|
|
|
//include JS to handling showing and hiding of bottom "action" tabs |
|
940
|
|
|
Requirements::javascript(DMS_DIR.'/javascript/DMSDocumentCMSFields.js'); |
|
941
|
|
|
Requirements::css(DMS_DIR.'/css/DMSDocumentCMSFields.css'); |
|
942
|
|
|
|
|
943
|
|
|
$fields = new FieldList(); //don't use the automatic scaffolding, it is slow and unnecessary here |
|
944
|
|
|
|
|
945
|
|
|
$extraTasks = ''; //additional text to inject into the list of tasks at the bottom of a DMSDocument CMSfield |
|
946
|
|
|
|
|
947
|
|
|
//get list of shortcode page relations |
|
948
|
|
|
$relationFinder = new ShortCodeRelationFinder(); |
|
949
|
|
|
$relationList = $relationFinder->getList($this->ID); |
|
950
|
|
|
|
|
951
|
|
|
$fieldsTop = $this->getFieldsForFile($relationList->count()); |
|
952
|
|
|
$fields->add($fieldsTop); |
|
953
|
|
|
|
|
954
|
|
|
$fields->add(new TextField('Title', 'Title')); |
|
955
|
|
|
$fields->add(new TextareaField('Description', 'Description')); |
|
956
|
|
|
|
|
957
|
|
|
$downloadBehaviorSource = array( |
|
958
|
|
|
'open' => _t('DMSDocument.OPENINBROWSER', 'Open in browser'), |
|
959
|
|
|
'download' => _t('DMSDocument.FORCEDOWNLOAD', 'Force download'), |
|
960
|
|
|
); |
|
961
|
|
|
$defaultDownloadBehaviour = Config::inst()->get('DMSDocument', 'default_download_behaviour'); |
|
962
|
|
|
if (!isset($downloadBehaviorSource[$defaultDownloadBehaviour])) { |
|
963
|
|
|
user_error('Default download behaviour "' . $defaultDownloadBehaviour . '" not supported.', E_USER_WARNING); |
|
964
|
|
|
} else { |
|
965
|
|
|
$downloadBehaviorSource[$defaultDownloadBehaviour] .= ' (' . _t('DMSDocument.DEFAULT', 'default') . ')'; |
|
966
|
|
|
} |
|
967
|
|
|
|
|
968
|
|
|
$fields->add( |
|
969
|
|
|
OptionsetField::create( |
|
970
|
|
|
'DownloadBehavior', |
|
971
|
|
|
_t('DMSDocument.DOWNLOADBEHAVIOUR', 'Download behavior'), |
|
972
|
|
|
$downloadBehaviorSource, |
|
973
|
|
|
$defaultDownloadBehaviour |
|
974
|
|
|
) |
|
975
|
|
|
->setDescription( |
|
976
|
|
|
'How the visitor will view this file. <strong>Open in browser</strong> ' |
|
977
|
|
|
. 'allows files to be opened in a new tab.' |
|
978
|
|
|
) |
|
979
|
|
|
); |
|
980
|
|
|
|
|
981
|
|
|
//create upload field to replace document |
|
982
|
|
|
$uploadField = new DMSUploadField('ReplaceFile', 'Replace file'); |
|
983
|
|
|
$uploadField->setConfig('allowedMaxFileNumber', 1); |
|
984
|
|
|
$uploadField->setConfig('downloadTemplateName', 'ss-dmsuploadfield-downloadtemplate'); |
|
985
|
|
|
$uploadField->setRecord($this); |
|
986
|
|
|
|
|
987
|
|
|
$gridFieldConfig = GridFieldConfig::create()->addComponents( |
|
988
|
|
|
new GridFieldToolbarHeader(), |
|
989
|
|
|
new GridFieldSortableHeader(), |
|
990
|
|
|
new GridFieldDataColumns(), |
|
991
|
|
|
new GridFieldPaginator(30), |
|
992
|
|
|
//new GridFieldEditButton(), |
|
993
|
|
|
new GridFieldDetailForm() |
|
994
|
|
|
); |
|
995
|
|
|
|
|
996
|
|
|
$gridFieldConfig->getComponentByType('GridFieldDataColumns') |
|
997
|
|
|
->setDisplayFields(array( |
|
998
|
|
|
'Title'=>'Title', |
|
999
|
|
|
'ClassName'=>'Page Type', |
|
1000
|
|
|
'ID'=>'Page ID' |
|
1001
|
|
|
)) |
|
1002
|
|
|
->setFieldFormatting(array( |
|
1003
|
|
|
'Title'=>sprintf( |
|
1004
|
|
|
'<a class=\"cms-panel-link\" href=\"%s/$ID\">$Title</a>', |
|
1005
|
|
|
singleton('CMSPageEditController')->Link('show') |
|
1006
|
|
|
) |
|
1007
|
|
|
)); |
|
1008
|
|
|
|
|
1009
|
|
|
$pagesGrid = GridField::create( |
|
1010
|
|
|
'Pages', |
|
1011
|
|
|
_t('DMSDocument.RelatedPages', 'Related Pages'), |
|
1012
|
|
|
$this->Pages(), |
|
1013
|
|
|
$gridFieldConfig |
|
1014
|
|
|
); |
|
1015
|
|
|
|
|
1016
|
|
|
$referencesGrid = GridField::create( |
|
1017
|
|
|
'References', |
|
1018
|
|
|
_t('DMSDocument.RelatedReferences', 'Related References'), |
|
1019
|
|
|
$relationList, |
|
1020
|
|
|
$gridFieldConfig |
|
1021
|
|
|
); |
|
1022
|
|
|
|
|
1023
|
|
|
if (DMSDocument_versions::$enable_versions) { |
|
1024
|
|
|
$versionsGridFieldConfig = GridFieldConfig::create()->addComponents( |
|
1025
|
|
|
new GridFieldToolbarHeader(), |
|
1026
|
|
|
new GridFieldSortableHeader(), |
|
1027
|
|
|
new GridFieldDataColumns(), |
|
1028
|
|
|
new GridFieldPaginator(30) |
|
1029
|
|
|
); |
|
1030
|
|
|
$versionsGridFieldConfig->getComponentByType('GridFieldDataColumns') |
|
1031
|
|
|
->setDisplayFields(Config::inst()->get('DMSDocument_versions', 'display_fields')) |
|
1032
|
|
|
->setFieldCasting(array('LastChanged'=>"Datetime->Ago")) |
|
1033
|
|
|
->setFieldFormatting( |
|
1034
|
|
|
array( |
|
1035
|
|
|
'FilenameWithoutID' => '<a target=\'_blank\' class=\'file-url\' href=\'$Link\'>' |
|
1036
|
|
|
. '$FilenameWithoutID</a>' |
|
1037
|
|
|
) |
|
1038
|
|
|
); |
|
1039
|
|
|
|
|
1040
|
|
|
$versionsGrid = GridField::create( |
|
1041
|
|
|
'Versions', |
|
1042
|
|
|
_t('DMSDocument.Versions', 'Versions'), |
|
1043
|
|
|
$this->getVersions(), |
|
1044
|
|
|
$versionsGridFieldConfig |
|
1045
|
|
|
); |
|
1046
|
|
|
$extraTasks .= '<li class="ss-ui-button" data-panel="find-versions">Versions</li>'; |
|
1047
|
|
|
} |
|
1048
|
|
|
|
|
1049
|
|
|
$fields->add(new LiteralField( |
|
1050
|
|
|
'BottomTaskSelection', |
|
1051
|
|
|
'<div id="Actions" class="field actions"><label class="left">Actions</label><ul>' |
|
1052
|
|
|
. '<li class="ss-ui-button" data-panel="embargo">Embargo</li>' |
|
1053
|
|
|
. '<li class="ss-ui-button" data-panel="expiry">Expiry</li>' |
|
1054
|
|
|
. '<li class="ss-ui-button" data-panel="replace">Replace</li>' |
|
1055
|
|
|
. '<li class="ss-ui-button" data-panel="find-usage">Usage</li>' |
|
1056
|
|
|
. '<li class="ss-ui-button" data-panel="find-references">References</li>' |
|
1057
|
|
|
. '<li class="ss-ui-button" data-panel="find-relateddocuments">Related Documents</li>' |
|
1058
|
|
|
. $extraTasks |
|
1059
|
|
|
. '</ul></div>' |
|
1060
|
|
|
)); |
|
1061
|
|
|
|
|
1062
|
|
|
$embargoValue = 'None'; |
|
1063
|
|
|
if ($this->EmbargoedIndefinitely) { |
|
1064
|
|
|
$embargoValue = 'Indefinitely'; |
|
1065
|
|
|
} elseif ($this->EmbargoedUntilPublished) { |
|
1066
|
|
|
$embargoValue = 'Published'; |
|
1067
|
|
|
} elseif (!empty($this->EmbargoedUntilDate)) { |
|
1068
|
|
|
$embargoValue = 'Date'; |
|
1069
|
|
|
} |
|
1070
|
|
|
$embargo = new OptionsetField( |
|
1071
|
|
|
'Embargo', |
|
1072
|
|
|
'Embargo', |
|
1073
|
|
|
array( |
|
1074
|
|
|
'None' => 'None', |
|
1075
|
|
|
'Published' => 'Hide document until page is published', |
|
1076
|
|
|
'Indefinitely' => 'Hide document indefinitely', |
|
1077
|
|
|
'Date' => 'Hide until set date' |
|
1078
|
|
|
), |
|
1079
|
|
|
$embargoValue |
|
1080
|
|
|
); |
|
1081
|
|
|
$embargoDatetime = DatetimeField::create('EmbargoedUntilDate', ''); |
|
1082
|
|
|
$embargoDatetime->getDateField() |
|
1083
|
|
|
->setConfig('showcalendar', true) |
|
1084
|
|
|
->setConfig('dateformat', 'dd-MM-yyyy') |
|
1085
|
|
|
->setConfig('datavalueformat', 'dd-MM-yyyy'); |
|
1086
|
|
|
|
|
1087
|
|
|
$expiryValue = 'None'; |
|
1088
|
|
|
if (!empty($this->ExpireAtDate)) { |
|
1089
|
|
|
$expiryValue = 'Date'; |
|
1090
|
|
|
} |
|
1091
|
|
|
$expiry = new OptionsetField( |
|
1092
|
|
|
'Expiry', |
|
1093
|
|
|
'Expiry', |
|
1094
|
|
|
array( |
|
1095
|
|
|
'None' => 'None', |
|
1096
|
|
|
'Date' => 'Set document to expire on' |
|
1097
|
|
|
), |
|
1098
|
|
|
$expiryValue |
|
1099
|
|
|
); |
|
1100
|
|
|
$expiryDatetime = DatetimeField::create('ExpireAtDate', ''); |
|
1101
|
|
|
$expiryDatetime->getDateField() |
|
1102
|
|
|
->setConfig('showcalendar', true) |
|
1103
|
|
|
->setConfig('dateformat', 'dd-MM-yyyy') |
|
1104
|
|
|
->setConfig('datavalueformat', 'dd-MM-yyyy'); |
|
1105
|
|
|
|
|
1106
|
|
|
// This adds all the actions details into a group. |
|
1107
|
|
|
// Embargo, History, etc to go in here |
|
1108
|
|
|
// These are toggled on and off via the Actions Buttons above |
|
1109
|
|
|
// exit('hit'); |
|
1110
|
|
|
$actionsPanel = FieldGroup::create( |
|
1111
|
|
|
FieldGroup::create($embargo, $embargoDatetime)->addExtraClass('embargo'), |
|
1112
|
|
|
FieldGroup::create($expiry, $expiryDatetime)->addExtraClass('expiry'), |
|
1113
|
|
|
FieldGroup::create($uploadField)->addExtraClass('replace'), |
|
1114
|
|
|
FieldGroup::create($pagesGrid)->addExtraClass('find-usage'), |
|
1115
|
|
|
FieldGroup::create($referencesGrid)->addExtraClass('find-references'), |
|
1116
|
|
|
FieldGroup::create($versionsGrid)->addExtraClass('find-versions'), |
|
1117
|
|
|
FieldGroup::create($this->getRelatedDocumentsGridField())->addExtraClass('find-relateddocuments') |
|
1118
|
|
|
); |
|
1119
|
|
|
|
|
1120
|
|
|
$actionsPanel->setName("ActionsPanel"); |
|
1121
|
|
|
$actionsPanel->addExtraClass("DMSDocumentActionsPanel"); |
|
1122
|
|
|
$fields->push($actionsPanel); |
|
1123
|
|
|
|
|
1124
|
|
|
$this->addPermissionsFields($fields); |
|
1125
|
|
|
$this->extend('updateCMSFields', $fields); |
|
1126
|
|
|
|
|
1127
|
|
|
return $fields; |
|
1128
|
|
|
} |
|
1129
|
|
|
|
|
1130
|
|
|
/** |
|
1131
|
|
|
* Adds permissions selection fields to the FieldList. |
|
1132
|
|
|
* |
|
1133
|
|
|
* @param FieldList $fields |
|
1134
|
|
|
*/ |
|
1135
|
|
|
public function addPermissionsFields($fields) |
|
1136
|
|
|
{ |
|
1137
|
|
|
$showFields = array( |
|
1138
|
|
|
'CanViewType' => '', |
|
1139
|
|
|
'ViewerGroups' => 'hide', |
|
1140
|
|
|
'CanEditType' => '', |
|
1141
|
|
|
'EditorGroups' => 'hide', |
|
1142
|
|
|
); |
|
1143
|
|
|
/** @var SiteTree $siteTree */ |
|
1144
|
|
|
$siteTree = singleton('SiteTree'); |
|
1145
|
|
|
$settingsFields = $siteTree->getSettingsFields(); |
|
1146
|
|
|
|
|
1147
|
|
|
foreach ($showFields as $name => $extraCss) { |
|
1148
|
|
|
$compositeName = "Root.Settings.$name"; |
|
1149
|
|
|
/** @var FormField $field */ |
|
1150
|
|
|
if ($field = $settingsFields->fieldByName($compositeName)) { |
|
1151
|
|
|
$field->addExtraClass($extraCss); |
|
1152
|
|
|
$title = str_replace('page', 'document', $field->Title()); |
|
1153
|
|
|
$field->setTitle($title); |
|
1154
|
|
|
|
|
1155
|
|
|
//Remove Inherited source option from DropdownField |
|
1156
|
|
|
if ($field instanceof DropdownField) { |
|
1157
|
|
|
$options = $field->getSource(); |
|
1158
|
|
|
unset($options['Inherit']); |
|
1159
|
|
|
$field->setSource($options); |
|
1160
|
|
|
} |
|
1161
|
|
|
$fields->push($field); |
|
1162
|
|
|
} |
|
1163
|
|
|
} |
|
1164
|
|
|
|
|
1165
|
|
|
$this->extend('updatePermissionsFields', $fields); |
|
1166
|
|
|
} |
|
1167
|
|
|
|
|
1168
|
|
|
public function onBeforeWrite() |
|
1169
|
|
|
{ |
|
1170
|
|
|
parent::onBeforeWrite(); |
|
1171
|
|
|
|
|
1172
|
|
|
if (isset($this->Embargo)) { |
|
1173
|
|
|
//set the embargo options from the OptionSetField created in the getCMSFields method |
|
1174
|
|
|
//do not write after clearing the embargo (write happens automatically) |
|
1175
|
|
|
$savedDate = $this->EmbargoedUntilDate; |
|
1176
|
|
|
$this->clearEmbargo(false); //clear all previous settings and re-apply them on save |
|
1177
|
|
|
|
|
1178
|
|
|
if ($this->Embargo == 'Published') { |
|
1179
|
|
|
$this->embargoUntilPublished(false); |
|
1180
|
|
|
} |
|
1181
|
|
|
if ($this->Embargo == 'Indefinitely') { |
|
1182
|
|
|
$this->embargoIndefinitely(false); |
|
1183
|
|
|
} |
|
1184
|
|
|
if ($this->Embargo == 'Date') { |
|
1185
|
|
|
$this->embargoUntilDate($savedDate, false); |
|
1186
|
|
|
} |
|
1187
|
|
|
} |
|
1188
|
|
|
|
|
1189
|
|
|
if (isset($this->Expiry)) { |
|
1190
|
|
|
if ($this->Expiry == 'Date') { |
|
1191
|
|
|
$this->expireAtDate($this->ExpireAtDate, false); |
|
1192
|
|
|
} else { |
|
1193
|
|
|
$this->clearExpiry(false); |
|
1194
|
|
|
} //clear all previous settings |
|
1195
|
|
|
} |
|
1196
|
|
|
} |
|
1197
|
|
|
|
|
1198
|
|
|
/** |
|
1199
|
|
|
* Return the relative URL of an icon for the file type, based on the |
|
1200
|
|
|
* {@link appCategory()} value. |
|
1201
|
|
|
* |
|
1202
|
|
|
* Images are searched for in "dms/images/app_icons/". |
|
1203
|
|
|
* |
|
1204
|
|
|
* @return string |
|
1205
|
|
|
*/ |
|
1206
|
|
|
public function Icon($ext) |
|
1207
|
|
|
{ |
|
1208
|
|
|
if (!Director::fileExists(DMS_DIR."/images/app_icons/{$ext}_32.png")) { |
|
1209
|
|
|
$ext = File::get_app_category($ext); |
|
1210
|
|
|
} |
|
1211
|
|
|
|
|
1212
|
|
|
if (!Director::fileExists(DMS_DIR."/images/app_icons/{$ext}_32.png")) { |
|
1213
|
|
|
$ext = "generic"; |
|
1214
|
|
|
} |
|
1215
|
|
|
|
|
1216
|
|
|
return DMS_DIR."/images/app_icons/{$ext}_32.png"; |
|
1217
|
|
|
} |
|
1218
|
|
|
|
|
1219
|
|
|
/** |
|
1220
|
|
|
* Return the extension of the file associated with the document |
|
1221
|
|
|
* |
|
1222
|
|
|
* @return string |
|
1223
|
|
|
*/ |
|
1224
|
|
|
public function getExtension() |
|
1225
|
|
|
{ |
|
1226
|
|
|
return strtolower(pathinfo($this->Filename, PATHINFO_EXTENSION)); |
|
1227
|
|
|
} |
|
1228
|
|
|
|
|
1229
|
|
|
/** |
|
1230
|
|
|
* @return string |
|
1231
|
|
|
*/ |
|
1232
|
|
|
public function getSize() |
|
1233
|
|
|
{ |
|
1234
|
|
|
$size = $this->getAbsoluteSize(); |
|
1235
|
|
|
return ($size) ? File::format_size($size) : false; |
|
1236
|
|
|
} |
|
1237
|
|
|
|
|
1238
|
|
|
/** |
|
1239
|
|
|
* Return the size of the file associated with the document. |
|
1240
|
|
|
* |
|
1241
|
|
|
* @return string |
|
1242
|
|
|
*/ |
|
1243
|
|
|
public function getAbsoluteSize() |
|
1244
|
|
|
{ |
|
1245
|
|
|
return file_exists($this->getFullPath()) ? filesize($this->getFullPath()) : null; |
|
1246
|
|
|
} |
|
1247
|
|
|
|
|
1248
|
|
|
/** |
|
1249
|
|
|
* An alias to DMSDocument::getSize() |
|
1250
|
|
|
* |
|
1251
|
|
|
* @return string |
|
1252
|
|
|
*/ |
|
1253
|
|
|
public function getFileSizeFormatted() |
|
1254
|
|
|
{ |
|
1255
|
|
|
return $this->getSize(); |
|
1256
|
|
|
} |
|
1257
|
|
|
|
|
1258
|
|
|
|
|
1259
|
|
|
/** |
|
1260
|
|
|
* @return FieldList |
|
1261
|
|
|
*/ |
|
1262
|
|
|
protected function getFieldsForFile($relationListCount) |
|
1263
|
|
|
{ |
|
1264
|
|
|
$extension = $this->getExtension(); |
|
1265
|
|
|
|
|
1266
|
|
|
$previewField = new LiteralField( |
|
1267
|
|
|
"ImageFull", |
|
1268
|
|
|
"<img id='thumbnailImage' class='thumbnail-preview' src='{$this->Icon($extension)}?r=" |
|
1269
|
|
|
. rand(1, 100000) . "' alt='{$this->Title}' />\n" |
|
1270
|
|
|
); |
|
1271
|
|
|
|
|
1272
|
|
|
//count the number of pages this document is published on |
|
1273
|
|
|
$publishedOnCount = $this->Pages()->Count(); |
|
1274
|
|
|
$publishedOnValue = "$publishedOnCount pages"; |
|
1275
|
|
|
if ($publishedOnCount == 1) { |
|
1276
|
|
|
$publishedOnValue = "$publishedOnCount page"; |
|
1277
|
|
|
} |
|
1278
|
|
|
|
|
1279
|
|
|
$relationListCountValue = "$relationListCount pages"; |
|
1280
|
|
|
if ($relationListCount == 1) { |
|
1281
|
|
|
$relationListCountValue = "$relationListCount page"; |
|
1282
|
|
|
} |
|
1283
|
|
|
|
|
1284
|
|
|
$fields = new FieldGroup( |
|
1285
|
|
|
$filePreview = CompositeField::create( |
|
1286
|
|
|
CompositeField::create( |
|
1287
|
|
|
$previewField |
|
1288
|
|
|
)->setName("FilePreviewImage")->addExtraClass('cms-file-info-preview'), |
|
1289
|
|
|
CompositeField::create( |
|
1290
|
|
|
CompositeField::create( |
|
1291
|
|
|
new ReadonlyField("ID", "ID number". ':', $this->ID), |
|
1292
|
|
|
new ReadonlyField( |
|
1293
|
|
|
"FileType", |
|
1294
|
|
|
_t('AssetTableField.TYPE', 'File type') . ':', |
|
1295
|
|
|
self::get_file_type($extension) |
|
1296
|
|
|
), |
|
1297
|
|
|
new ReadonlyField( |
|
1298
|
|
|
"Size", |
|
1299
|
|
|
_t('AssetTableField.SIZE', 'File size') . ':', |
|
1300
|
|
|
$this->getFileSizeFormatted() |
|
1301
|
|
|
), |
|
1302
|
|
|
$urlField = new ReadonlyField( |
|
1303
|
|
|
'ClickableURL', |
|
1304
|
|
|
_t('AssetTableField.URL', 'URL'), |
|
1305
|
|
|
sprintf( |
|
1306
|
|
|
'<a href="%s" target="_blank" class="file-url">%s</a>', |
|
1307
|
|
|
$this->getLink(), |
|
1308
|
|
|
$this->getLink() |
|
1309
|
|
|
) |
|
1310
|
|
|
), |
|
1311
|
|
|
new ReadonlyField("FilenameWithoutIDField", "Filename". ':', $this->getFilenameWithoutID()), |
|
1312
|
|
|
new DateField_Disabled( |
|
1313
|
|
|
"Created", |
|
1314
|
|
|
_t('AssetTableField.CREATED', 'First uploaded') . ':', |
|
1315
|
|
|
$this->Created |
|
1316
|
|
|
), |
|
1317
|
|
|
new DateField_Disabled( |
|
1318
|
|
|
"LastEdited", |
|
1319
|
|
|
_t('AssetTableField.LASTEDIT', 'Last changed') . ':', |
|
1320
|
|
|
$this->LastEdited |
|
1321
|
|
|
), |
|
1322
|
|
|
new DateField_Disabled( |
|
1323
|
|
|
"LastChanged", |
|
1324
|
|
|
_t('AssetTableField.LASTCHANGED', 'Last replaced') . ':', |
|
1325
|
|
|
$this->LastChanged |
|
1326
|
|
|
), |
|
1327
|
|
|
new ReadonlyField("PublishedOn", "Published on". ':', $publishedOnValue), |
|
1328
|
|
|
new ReadonlyField("ReferencedOn", "Referenced on". ':', $relationListCountValue), |
|
1329
|
|
|
new ReadonlyField("ViewCount", "View count". ':', $this->ViewCount) |
|
1330
|
|
|
) |
|
1331
|
|
|
)->setName("FilePreviewData")->addExtraClass('cms-file-info-data') |
|
1332
|
|
|
)->setName("FilePreview")->addExtraClass('cms-file-info') |
|
1333
|
|
|
); |
|
1334
|
|
|
|
|
1335
|
|
|
$fields->setName('FileP'); |
|
1336
|
|
|
$urlField->dontEscape = true; |
|
1337
|
|
|
|
|
1338
|
|
|
return $fields; |
|
1339
|
|
|
} |
|
1340
|
|
|
|
|
1341
|
|
|
/** |
|
1342
|
|
|
* Takes a file and adds it to the DMSDocument storage, replacing the |
|
1343
|
|
|
* current file. |
|
1344
|
|
|
* |
|
1345
|
|
|
* @param File $file |
|
1346
|
|
|
* |
|
1347
|
|
|
* @return $this |
|
1348
|
|
|
*/ |
|
1349
|
|
|
public function ingestFile($file) |
|
1350
|
|
|
{ |
|
1351
|
|
|
$this->replaceDocument($file); |
|
1352
|
|
|
$file->delete(); |
|
1353
|
|
|
|
|
1354
|
|
|
return $this; |
|
1355
|
|
|
} |
|
1356
|
|
|
|
|
1357
|
|
|
/** |
|
1358
|
|
|
* Get a data list of documents related to this document |
|
1359
|
|
|
* |
|
1360
|
|
|
* @return DataList |
|
1361
|
|
|
*/ |
|
1362
|
|
|
public function getRelatedDocuments() |
|
1363
|
|
|
{ |
|
1364
|
|
|
$documents = $this->RelatedDocuments(); |
|
1365
|
|
|
|
|
1366
|
|
|
$this->extend('updateRelatedDocuments', $documents); |
|
1367
|
|
|
|
|
1368
|
|
|
return $documents; |
|
1369
|
|
|
} |
|
1370
|
|
|
|
|
1371
|
|
|
/** |
|
1372
|
|
|
* Get a GridField for managing related documents |
|
1373
|
|
|
* |
|
1374
|
|
|
* @return GridField |
|
1375
|
|
|
*/ |
|
1376
|
|
|
protected function getRelatedDocumentsGridField() |
|
1377
|
|
|
{ |
|
1378
|
|
|
$gridField = GridField::create( |
|
1379
|
|
|
'RelatedDocuments', |
|
1380
|
|
|
_t('DMSDocument.RELATEDDOCUMENTS', 'Related Documents'), |
|
1381
|
|
|
$this->RelatedDocuments(), |
|
1382
|
|
|
new GridFieldConfig_RelationEditor |
|
1383
|
|
|
); |
|
1384
|
|
|
|
|
1385
|
|
|
$gridField->getConfig()->removeComponentsByType('GridFieldAddNewButton'); |
|
1386
|
|
|
// Move the autocompleter to the left |
|
1387
|
|
|
$gridField->getConfig()->removeComponentsByType('GridFieldAddExistingAutocompleter'); |
|
1388
|
|
|
$gridField->getConfig()->addComponent(new GridFieldAddExistingAutocompleter('buttons-before-left')); |
|
1389
|
|
|
|
|
1390
|
|
|
$this->extend('updateRelatedDocumentsGridField', $gridField); |
|
1391
|
|
|
|
|
1392
|
|
|
return $gridField; |
|
1393
|
|
|
} |
|
1394
|
|
|
|
|
1395
|
|
|
/** |
|
1396
|
|
|
* Checks at least one group is selected if CanViewType || CanEditType == 'OnlyTheseUsers' |
|
1397
|
|
|
* |
|
1398
|
|
|
* @return ValidationResult |
|
1399
|
|
|
*/ |
|
1400
|
|
|
protected function validate() |
|
1401
|
|
|
{ |
|
1402
|
|
|
$valid = parent::validate(); |
|
1403
|
|
|
|
|
1404
|
|
|
if ($this->CanViewType == 'OnlyTheseUsers' && !$this->ViewerGroups()->count()) { |
|
1405
|
|
|
$valid->error("Selecting 'Only these people' from a viewers list needs at least one group selected."); |
|
1406
|
|
|
} |
|
1407
|
|
|
|
|
1408
|
|
|
if ($this->CanEditType == 'OnlyTheseUsers' && !$this->EditorGroups()->count()) { |
|
1409
|
|
|
$valid->error("Selecting 'Only these people' from a editors list needs at least one group selected."); |
|
1410
|
|
|
} |
|
1411
|
|
|
|
|
1412
|
|
|
return $valid; |
|
1413
|
|
|
} |
|
1414
|
|
|
|
|
1415
|
|
|
|
|
1416
|
|
|
} |
|
1417
|
|
|
|
The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.
The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.
To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.