Completed
Push — master ( b4e5c2...6db701 )
by Daniel
05:37 queued 03:12
created

code/cms/DMSDocumentAddController.php (2 issues)

Upgrade to new PHP Analysis Engine

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

1
<?php
2
3
/**
4
 * @package dms
5
 */
6
class DMSDocumentAddController extends LeftAndMain
7
{
8
    private static $url_segment = 'pages/adddocument';
9
    private static $url_priority = 60;
10
    private static $required_permission_codes = 'CMS_ACCESS_AssetAdmin';
11
    private static $menu_title = 'Edit Page';
12
    private static $tree_class = 'SiteTree';
13
    private static $session_namespace = 'CMSMain';
14
15
    /**
16
     * Allowed file upload extensions, will be merged with `$allowed_extensions` from {@link File}
17
     *
18
     * @config
19
     * @var array
20
     */
21
    private static $allowed_extensions = array();
22
23
    private static $allowed_actions = array(
24
        'getEditForm',
25
        'documentautocomplete',
26
        'linkdocument',
27
        'documentlist'
28
    );
29
30
    /**
31
     * Custom currentPage() method to handle opening the 'root' folder
32
     *
33
     * @return SiteTree
34
     */
35
    public function currentPage()
36
    {
37
        $id = $this->currentPageID();
38
        if ($id === 0) {
39
            return SiteTree::singleton();
40
        }
41
        return parent::currentPage();
42
    }
43
44
    /**
45
     * Return fake-ID "root" if no ID is found (needed to upload files into the root-folder). Otherwise the page ID
46
     * is passed in from the {@link DMSGridFieldAddNewButton}.
47
     *
48
     * @return int
49
     */
50
    public function currentPageID()
51
    {
52
        return (int) $this->getRequest()->getVar('page_id');
53
    }
54
55
    /**
56
     * Get the current document set, if a document set ID was provided
57
     *
58
     * @return DMSDocumentSet
59
     */
60
    public function getCurrentDocumentSet()
61
    {
62
        if ($id = $this->getRequest()->getVar('dsid')) {
63
            return DMSDocumentSet::get()->byId($id);
64
        }
65
        return singleton('DMSDocumentSet');
66
    }
67
68
    /**
69
     * @return Form
70
     * @todo what template is used here? AssetAdmin_UploadContent.ss doesn't seem to be used anymore
71
     */
72
    public function getEditForm($id = null, $fields = null)
73
    {
74
        Requirements::javascript(FRAMEWORK_DIR . '/javascript/AssetUploadField.js');
75
        Requirements::css(FRAMEWORK_DIR . '/css/AssetUploadField.css');
76
        Requirements::css(DMS_DIR . '/dist/css/cmsbundle.css');
77
78
        /** @var SiteTree $page */
79
        $page = $this->currentPage();
80
        /** @var DMSDocumentSet $documentSet */
81
        $documentSet = $this->getCurrentDocumentSet();
82
83
        $uploadField = DMSUploadField::create('AssetUploadField', '');
84
        $uploadField->setConfig('previewMaxWidth', 40);
85
        $uploadField->setConfig('previewMaxHeight', 30);
86
        // Required to avoid Solr reindexing (often used alongside DMS) to
87
        // return 503s because of too many concurrent reindex requests
88
        $uploadField->setConfig('sequentialUploads', 1);
89
        $uploadField->addExtraClass('ss-assetuploadfield');
90
        $uploadField->removeExtraClass('ss-uploadfield');
91
        $uploadField->setTemplate('AssetUploadField');
92
        $uploadField->setRecord($documentSet);
93
94
        $uploadField->getValidator()->setAllowedExtensions($this->getAllowedExtensions());
95
        $exts = $uploadField->getValidator()->getAllowedExtensions();
96
97
        asort($exts);
98
        $backlink = $this->Backlink();
99
        $done = "
100
		<a class=\"ss-ui-button ss-ui-action-constructive cms-panel-link ui-corner-all\" href=\"" . $backlink . "\">
101
			" . _t('UploadField.DONE', 'DONE') . "
102
		</a>";
103
104
        $addExistingField = new DMSDocumentAddExistingField(
105
            'AddExisting',
106
            _t('DMSDocumentAddExistingField.ADDEXISTING', 'Add Existing')
107
        );
108
        $addExistingField->setRecord($documentSet);
109
110
        $form = new Form(
111
            $this,
112
            'getEditForm',
113
            new FieldList(
114
                new TabSet(
115
                    _t('DMSDocumentAddController.MAINTAB', 'Main'),
116
                    new Tab(
117
                        _t('UploadField.FROMCOMPUTER', 'From your computer'),
118
                        $uploadField,
119
                        new LiteralField(
120
                            'AllowedExtensions',
121
                            sprintf(
122
                                '<p>%s: %s</p>',
123
                                _t('AssetAdmin.ALLOWEDEXTS', 'Allowed extensions'),
124
                                implode('<em>, </em>', $exts)
125
                            )
126
                        )
127
                    ),
128
                    new Tab(
129
                        _t('UploadField.FROMCMS', 'From the CMS'),
130
                        $addExistingField
131
                    )
132
                )
133
            ),
134
            new FieldList(
135
                new LiteralField('doneButton', $done)
136
            )
137
        );
138
        $form->addExtraClass('center cms-edit-form ' . $this->BaseCSSClasses());
139
        $form->Backlink = $backlink;
140
        // Don't use AssetAdmin_EditForm, as it assumes a different panel structure
141
        $form->setTemplate($this->getTemplatesWithSuffix('_EditForm'));
142
        $form->Fields()->push(HiddenField::create('ID', false, $documentSet->ID));
143
        $form->Fields()->push(HiddenField::create('DSID', false, $documentSet->ID));
144
145
        return $form;
146
    }
147
148
    /**
149
     * @return ArrayList
150
     */
151
    public function Breadcrumbs($unlinked = false)
152
    {
153
        $items = parent::Breadcrumbs($unlinked);
154
155
        // The root element should explicitly point to the root node.
156
        $items[0]->Link = Controller::join_links(singleton('CMSPageEditController')->Link('show'), 0);
157
158
        // Enforce linkage of hierarchy to AssetAdmin
159
        foreach ($items as $item) {
160
            $baselink = $this->Link('show');
161
            if (strpos($item->Link, $baselink) !== false) {
162
                $item->Link = str_replace($baselink, singleton('CMSPageEditController')->Link('show'), $item->Link);
163
            }
164
        }
165
166
        $items->push(new ArrayData(array(
167
            'Title' => _t('DMSDocumentSet.ADDDOCUMENTBUTTON', 'Add Document'),
168
            'Link' => $this->Link()
169
        )));
170
171
        return $items;
172
    }
173
174
    /**
175
     * Returns the link to be used to return the user after uploading a document. Scenarios:
176
     *
177
     * 1) Page context: page ID and document set ID provided, redirect back to the page and document set
178
     * 2) Document set context: no page ID, document set ID provided, redirect back to document set in ModelAdmin
179
     * 3) Document context: no page ID and no document set ID provided, redirect back to documents in ModelAdmin
180
     *
181
     * @return string
182
     */
183
    public function Backlink()
184
    {
185
        if (!$this->getRequest()->getVar('dsid') || !$this->currentPageID()) {
186
            $modelAdmin = new DMSDocumentAdmin;
187
            $modelAdmin->init();
188
189
            if ($this->getRequest()->getVar('dsid')) {
190
                return Controller::join_links(
191
                    $modelAdmin->Link('DMSDocumentSet'),
192
                    'EditForm/field/DMSDocumentSet/item',
193
                    $this->getRequest()->getVar('dsid'),
194
                    'edit'
195
                );
196
            }
197
            return $modelAdmin->Link();
198
        }
199
200
        return $this->getPageEditLink($this->currentPageID(), $this->getRequest()->getVar('dsid'));
201
    }
202
203
    /**
204
     * Return a link to edit a page, deep linking into the document set given
205
     *
206
     * @param  int $pageId
207
     * @param  int $documentSetId
208
     * @return string
209
     */
210
    protected function getPageEditLink($pageId, $documentSetId)
211
    {
212
        return Controller::join_links(
213
            CMSPageEditController::singleton()->getEditForm($pageId)->FormAction(),
214
            'field/Document Sets/item',
215
            $documentSetId
216
        );
217
    }
218
219
    public function documentautocomplete()
220
    {
221
        $term = (string) $this->getRequest()->getVar('term');
222
        $termSql = Convert::raw2sql($term);
223
        $data = DMSDocument::get()
224
            ->where(
225
                '("ID" LIKE \'%' . $termSql . '%\' OR "Filename" LIKE \'%' . $termSql . '%\''
226
                . ' OR "Title" LIKE \'%' . $termSql . '%\')'
227
            )
228
            ->sort('ID ASC')
229
            ->limit(20);
230
231
        $return = array();
232
        foreach ($data as $doc) {
233
            $return[] = array(
234
                'label' => $doc->ID . ' - ' . $doc->Title,
235
                'value' => $doc->ID
236
            );
237
        }
238
239
        return Convert::raw2json($return);
240
    }
241
242
    /**
243
     * Link an existing document to the given document set ID
244
     * @return string JSON
245
     */
246
    public function linkdocument()
247
    {
248
        $return = array('error' => _t('UploadField.FIELDNOTSET', 'Could not add document to page'));
249
        $documentSet = $this->getCurrentDocumentSet();
250
        if (!empty($documentSet)) {
251
            $document = DMSDocument::get()->byId($this->getRequest()->getVar('documentID'));
252
            $documentSet->Documents()->add($document);
253
254
            $buttonText = '<button class="ss-uploadfield-item-edit ss-ui-button ui-corner-all"'
255
                . ' title="' . _t('DMSDocument.EDITDOCUMENT', 'Edit this document') . '" data-icon="pencil">'
256
                . _t('DMSDocument.EDIT', 'Edit') . '<span class="toggle-details">'
257
                . '<span class="toggle-details-icon"></span></span></button>';
258
259
            // Collect all output data.
260
            $return = array(
261
                'id' => $document->ID,
262
                'name' => $document->getTitle(),
263
                'thumbnail_url' => $document->Icon($document->getExtension()),
264
                'edit_url' => $this->getEditForm()->Fields()->fieldByName('Main.From your computer.AssetUploadField')
265
                    ->getItemHandler($document->ID)->EditLink(),
266
                'size' => $document->getFileSizeFormatted(),
267
                'buttons' => $buttonText,
268
                'showeditform' => true
269
            );
270
        }
271
272
        return Convert::raw2json($return);
273
    }
274
275
    /**
276
     * Returns HTML representing a list of documents that are associated with the given page ID, across all document
277
     * sets.
278
     *
279
     * @return string HTML
280
     */
281
    public function documentlist()
282
    {
283
        if (!$this->getRequest()->getVar('pageID')) {
284
            return $this->httpError(400);
285
        }
286
287
        $page = SiteTree::get()->byId($this->getRequest()->getVar('pageID'));
288
289
        if ($page && $page->getAllDocuments()->count() > 0) {
290
            $list = '<ul>';
291
292
            foreach ($page->getAllDocuments() as $document) {
293
                $list .= sprintf(
294
                    '<li><a class="add-document" data-document-id="%s">%s</a></li>',
295
                    $document->ID,
296
                    $document->ID . ' - '. Convert::raw2xml($document->Title)
297
                );
298
            }
299
300
            $list .= '</ul>';
301
302
            return $list;
303
        }
304
305
        return sprintf(
306
            '<p>%s</p>',
307
            _t('DMSDocumentAddController.NODOCUMENTS', 'There are no documents attached to the selected page.')
308
        );
309
    }
310
311
    /**
312
     * Get an array of allowed file upload extensions, merged with {@link File} and extra configuration from this
313
     * class
314
     *
315
     * @return array
316
     */
317
    public function getAllowedExtensions()
318
    {
319
        return array_filter(
320
            array_merge(
321
                (array) Config::inst()->get('File', 'allowed_extensions'),
322
                (array) $this->config()->get('allowed_extensions')
323
            )
324
        );
325
    }
326
327
    /**
328
     * Overrides the parent method to allow users with access to DMS admin to access this controller
329
     *
330
     * @param Member $member
0 ignored issues
show
Should the type for parameter $member not be Member|null?

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

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

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

Loading history...
331
     * @return bool
332
     */
333
    public function canView($member = null)
334
    {
335 View Code Duplication
        if (!$member || !(is_a($member, 'Member')) || is_numeric($member)) {
336
            $member = Member::currentUser();
337
        }
338
339
        if ($member &&
340
            Permission::checkMember(
341
                $member,
342
                array(
343
                    'CMS_ACCESS_DMSDocumentAdmin',
344
                )
345
            )
346
        ) {
347
            return true;
348
        }
349
        return parent::canView($member);
0 ignored issues
show
It seems like $member defined by \Member::currentUser() on line 336 can also be of type object<DataObject>; however, LeftAndMain::canView() does only seem to accept object<Member>|null, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
350
    }
351
}
352