Completed
Push — master ( e4ab2b...e8d46a )
by Franco
13s
created

code/model/DMSDocumentSet.php (1 issue)

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
 * A document set is attached to Pages, and contains many DMSDocuments
4
 *
5
 * @property Varchar Title
6
 * @property  Text KeyValuePairs
7
 * @property  Enum SortBy
8
 * @property Enum SortByDirection
9
 */
10
class DMSDocumentSet extends DataObject
11
{
12
    private static $db = array(
13
        'Title' => 'Varchar(255)',
14
        'KeyValuePairs' => 'Text',
15
        'SortBy' => "Enum('LastEdited,Created,Title')')",
16
        'SortByDirection' => "Enum('DESC,ASC')')",
17
    );
18
19
    private static $has_one = array(
20
        'Page' => 'SiteTree',
21
    );
22
23
    private static $many_many = array(
24
        'Documents' => 'DMSDocument',
25
    );
26
27
    private static $many_many_extraFields = array(
28
        'Documents' => array(
29
            // Flag indicating if a document was added directly to a set - in which case it is set - or added
30
            // via the query-builder.
31
            'ManuallyAdded' => 'Boolean(1)',
32
        ),
33
    );
34
35
    /**
36
     * Retrieve a list of the documents in this set. An extension hook is provided before the result is returned.
37
     *
38
     * You can attach an extension to this event:
39
     *
40
     * <code>
41
     * public function updateDocuments($document)
42
     * {
43
     *     // do something
44
     * }
45
     * </code>
46
     *
47
     * @return DataList|null
48
     */
49
    public function getDocuments()
50
    {
51
        $documents = $this->Documents();
52
        $this->extend('updateDocuments', $documents);
53
        return $documents;
54
    }
55
56
    /**
57
     * Put the "documents" list into the main tab instead of its own tab, and replace the default "Add Document" button
58
     * with a customised button for DMS documents
59
     *
60
     * @return FieldList
61
     */
62
    public function getCMSFields()
63
    {
64
        // PHP 5.3 only
65
        $self = $this;
66
        $this->beforeUpdateCMSFields(function (FieldList $fields) use ($self) {
67
            $fields->removeFieldsFromTab(
68
                'Root.Main',
69
                array('KeyValuePairs', 'SortBy', 'SortByDirection')
70
            );
71
            // Don't put the GridField for documents in until the set has been created
72
            if (!$self->isInDB()) {
73
                $fields->addFieldToTab(
74
                    'Root.Main',
75
                    LiteralField::create(
76
                        'GridFieldNotice',
77
                        '<p class="message warning">' . _t(
78
                            'DMSDocumentSet.GRIDFIELD_NOTICE',
79
                            'Managing documents will be available once you have created this document set.'
80
                        ) . '</p>'
81
                    ),
82
                    'Title'
83
                );
84
            } else {
85
                // Document listing
86
                $gridFieldConfig = GridFieldConfig::create()
87
                    ->addComponents(
88
                        new GridFieldToolbarHeader(),
89
                        new GridFieldFilterHeader(),
90
                        new GridFieldSortableHeader(),
91
                        new GridFieldDataColumns(),
92
                        new GridFieldEditButton(),
93
                        // Special delete dialog to handle custom behaviour of unlinking and deleting
94
                        new GridFieldDeleteAction(true),
95
                        new GridFieldDetailForm()
96
                    );
97
98
                if (class_exists('GridFieldPaginatorWithShowAll')) {
99
                    $paginatorComponent = new GridFieldPaginatorWithShowAll(15);
100
                } else {
101
                    $paginatorComponent = new GridFieldPaginator(15);
102
                }
103
                $gridFieldConfig->addComponent($paginatorComponent);
104
105
                if (class_exists('GridFieldSortableRows')) {
106
                    $sortableComponent = new GridFieldSortableRows('DocumentSort');
107
                    // setUsePagination method removed from newer version of SortableGridField.
108
                    if (method_exists($sortableComponent, 'setUsePagination')) {
109
                        $sortableComponent->setUsePagination(false)->setForceRedraw(true);
110
                    }
111
                    $gridFieldConfig->addComponent($sortableComponent);
112
                }
113
114
                $gridFieldConfig->getComponentByType('GridFieldDataColumns')
115
                    ->setDisplayFields($self->getDocumentDisplayFields())
116
                    ->setFieldCasting(array('LastEdited' => 'Datetime->Ago'))
117
                    ->setFieldFormatting(
118
                        array(
119
                            'FilenameWithoutID' => '<a target=\'_blank\' class=\'file-url\' href=\'$Link\'>$FilenameWithoutID</a>',
120
                            'ManuallyAdded' => function ($value) {
121
                                if ($value) {
122
                                    return _t('DMSDocumentSet.MANUAL', 'Manually');
123
                                }
124
                                return _t('DMSDocumentSet.QUERYBUILDER', 'Query Builder');
125
                            }
126
                        )
127
                    );
128
129
                // Override delete functionality with this class
130
                $gridFieldConfig->getComponentByType('GridFieldDetailForm')
131
                    ->setItemRequestClass('DMSGridFieldDetailForm_ItemRequest');
132
                $gridField = GridField::create(
133
                    'Documents',
134
                    false,
135
                    $self->Documents(),
136
                    $gridFieldConfig
137
                );
138
                $gridField->setModelClass('DMSDocument');
139
                $gridField->addExtraClass('documents');
140
141
                $gridFieldConfig->addComponent(
142
                    $addNewButton = new DMSGridFieldAddNewButton,
143
                    'GridFieldExportButton'
144
                );
145
                $addNewButton->setDocumentSetId($self->ID);
146
147
                $fields->removeByName('Documents');
148
                $fields->addFieldsToTab(
149
                    'Root.Main',
150
                    array(
151
                        $gridField,
152
                        HiddenField::create('DMSShortcodeHandlerKey', false, DMS::inst()->getShortcodeHandlerKey())
153
                    )
154
                );
155
                $self->addQueryFields($fields);
156
            }
157
        });
158
        $this->addRequirements();
159
        return parent::getCMSFields();
160
    }
161
162
    /**
163
     * Add required CSS and Javascript requirements for managing documents
164
     *
165
     * @return $this
166
     */
167
    protected function addRequirements()
168
    {
169
        // Javascript to customize the grid field for the DMS document (overriding entwine
170
        // in FRAMEWORK_DIR.'/javascript/GridField.js'
171
        Requirements::javascript(DMS_DIR . '/javascript/DMSGridField.js');
172
        Requirements::css(DMS_DIR . '/dist/css/dmsbundle.css');
173
174
        // Javascript for the link editor pop-up in TinyMCE
175
        Requirements::javascript(DMS_DIR . '/javascript/DocumentHtmlEditorFieldToolbar.js');
176
177
        return $this;
178
    }
179
180
    /**
181
     * Adds the query fields to build the document logic to the DMSDocumentSet.
182
     *
183
     * To extend use the following from within an Extension subclass:
184
     *
185
     * <code>
186
     * public function updateQueryFields($result)
187
     * {
188
     *     // Do something here
189
     * }
190
     * </code>
191
     *
192
     * @param FieldList $fields
193
     */
194
    public function addQueryFields($fields)
195
    {
196
        /** @var DMSDocument $doc */
197
        $doc = singleton('DMSDocument');
198
        /** @var FormField $field */
199
        $dmsDocFields = $doc->scaffoldSearchFields(array('fieldClasses' => true));
200
        $membersMap = Member::get()->map('ID', 'Name')->toArray();
201
        asort($membersMap);
202
203
        foreach ($dmsDocFields as $field) {
204
            if ($field instanceof ListboxField) {
205
                $map = ($field->getName() === 'Tags__ID') ? $doc->getAllTagsMap() : $membersMap;
0 ignored issues
show
Documentation Bug introduced by
The method getAllTagsMap does not exist on object<DMSDocument>? Since you implemented __call, maybe consider adding a @method annotation.

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

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

class ParentClass {
    private $data = array();

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

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

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
206
                $field->setMultiple(true)->setSource($map);
207
            }
208
        }
209
        $keyValPairs = JsonField::create('KeyValuePairs', $dmsDocFields->toArray());
210
211
        // Now lastly add the sort fields
212
        $sortedBy = FieldGroup::create('SortedBy', array(
213
            DropdownField::create('SortBy', '', array(
214
                'LastEdited'  => 'Last changed',
215
                'Created'     => 'Created',
216
                'Title'       => 'Document title',
217
            ), 'LastEdited'),
218
            DropdownField::create('SortByDirection', '', $this->dbObject('SortByDirection')->enumValues(), 'DESC'),
219
        ));
220
221
        $sortedBy->setTitle(_t('DMSDocumentSet.SORTED_BY', 'Sort the document set by:'));
222
        $fields->addFieldsToTab('Root.QueryBuilder', array($keyValPairs, $sortedBy));
223
        $this->extend('updateQueryFields', $fields);
224
    }
225
226
    public function onBeforeWrite()
227
    {
228
        parent::onBeforeWrite();
229
230
        $this->saveLinkedDocuments();
231
    }
232
233
    /**
234
     * Retrieve a list of the documents in this set. An extension hook is provided before the result is returned.
235
     */
236
    public function saveLinkedDocuments()
237
    {
238
        if (empty($this->KeyValuePairs) || !$this->isChanged('KeyValuePairs')) {
239
            return;
240
        }
241
242
        $keyValuesPair = Convert::json2array($this->KeyValuePairs);
243
244
        /** @var DMSDocument $dmsDoc */
245
        $dmsDoc = singleton('DMSDocument');
246
        $context = $dmsDoc->getDefaultSearchContext();
247
248
        $sortBy = $this->SortBy ? $this->SortBy : 'LastEdited';
249
        $sortByDirection = $this->SortByDirection ? $this->SortByDirection : 'DESC';
250
        $sortedBy = sprintf('%s %s', $sortBy, $sortByDirection);
251
252
        /** @var DataList $documents */
253
        $documents = $context->getResults($keyValuesPair, $sortedBy);
254
        $documents = $this->addEmbargoConditions($documents);
255
        $documents = $this->addQueryBuilderSearchResults($documents);
256
    }
257
258
    /**
259
     * Add embargo date conditions to a search query
260
     *
261
     * @param  DataList $documents
262
     * @return DataList
263
     */
264
    protected function addEmbargoConditions(DataList $documents)
265
    {
266
        $now = SS_Datetime::now()->Rfc2822();
267
268
        return $documents->where(
269
            "\"EmbargoedIndefinitely\" = 0 AND "
270
            . " \"EmbargoedUntilPublished\" = 0 AND "
271
            . "(\"EmbargoedUntilDate\" IS NULL OR "
272
            . "(\"EmbargoedUntilDate\" IS NOT NULL AND '{$now}' >= \"EmbargoedUntilDate\")) AND "
273
            . "\"ExpireAtDate\" IS NULL OR (\"ExpireAtDate\" IS NOT NULL AND '{$now}' < \"ExpireAtDate\")"
274
        );
275
    }
276
277
    /**
278
     * Remove all ManuallyAdded = 0 original results and add in the new documents returned by the search context
279
     *
280
     * @param  DataList $documents
281
     * @return DataList
282
     */
283
    protected function addQueryBuilderSearchResults(DataList $documents)
284
    {
285
        /** @var ManyManyList $originals Documents that belong to just this set. */
286
        $originals = $this->Documents();
287
        $originals->removeByFilter('"ManuallyAdded" = 0');
288
289
        foreach ($documents as $document) {
290
            $originals->add($document, array('ManuallyAdded' => 0));
291
        }
292
293
        return $originals;
294
    }
295
296
    /**
297
     * Customise the display fields for the documents GridField
298
     *
299
     * @return array
300
     */
301
    public function getDocumentDisplayFields()
302
    {
303
        return array_merge(
304
            (array) DMSDocument::create()->config()->get('display_fields'),
305
            array('ManuallyAdded' => _t('DMSDocumentSet.ADDEDMETHOD', 'Added'))
306
        );
307
    }
308
}
309