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