DMSSiteTreeExtension::onBeforeDelete()   A
last analyzed

Complexity

Conditions 5
Paths 8

Size

Total Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 20
rs 9.2888
c 0
b 0
f 0
cc 5
nc 8
nop 0
1
<?php
2
3
/**
4
 * @package dms
5
 */
6
class DMSSiteTreeExtension extends DataExtension
7
{
8
    private static $has_many = array(
9
        'DocumentSets' => 'DMSDocumentSet'
10
    );
11
12
    public function updateCMSFields(FieldList $fields)
13
    {
14
        // Ability to disable document sets for a Page
15
        if (!$this->owner->config()->get('documents_enabled')) {
16
            return;
17
        }
18
19
        // Hides the DocumentSets tab if the user has no permisions
20
        if (!Permission::checkMember(
21
            Member::currentUser(),
22
            array('ADMIN', 'CMS_ACCESS_DMSDocumentAdmin')
23
        )
24
        ) {
25
            return;
26
        }
27
28
        $gridField = GridField::create(
29
            'DocumentSets',
30
            false,
31
            $this->owner->DocumentSets(), //->Sort('DocumentSort'),
32
            $config = new GridFieldConfig_RelationEditor
33
        );
34
        $gridField->addExtraClass('documentsets');
35
36
        // Only show document sets in the autocompleter that have not been assigned to a page already
37
        $config->getComponentByType('GridFieldAddExistingAutocompleter')->setSearchList(
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface GridFieldComponent as the method setSearchList() does only exist in the following implementations of said interface: GridFieldAddExistingAutocompleter, GridFieldAddExistingSearchButton.

Let’s take a look at an example:

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

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

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

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

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

Available Fixes

  1. Change the type-hint for the parameter:

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

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

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
38
            DMSDocumentSet::get()->filter(array('PageID' => 0))
39
        );
40
41
        $fields->addFieldToTab(
42
            'Root.DocumentSets',
43
            $gridField
44
        );
45
46
        $fields
47
            ->findOrMakeTab('Root.DocumentSets')
48
            ->setTitle(_t(
49
                __CLASS__ . '.DocumentSetsTabTitle',
50
                'Document Sets ({count})',
51
                array('count' => $this->owner->DocumentSets()->count())
0 ignored issues
show
Documentation introduced by
array('count' => $this->...ocumentSets()->count()) is of type array<string,?,{"count":"?"}>, but the function expects a string.

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

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

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

function acceptsInteger($int) { }

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

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
52
            ));
53
    }
54
55
    /**
56
     * Get a list of document sets for the owner page
57
     *
58
     * @return ArrayList
59
     */
60
    public function getDocumentSets()
61
    {
62
        return $this->owner->DocumentSets();
63
    }
64
65
    /**
66
     * Get a list of all documents from all document sets for the owner page
67
     *
68
     * @return ArrayList
69
     */
70
    public function getAllDocuments()
71
    {
72
        $documents = ArrayList::create();
73
74
        foreach ($this->getDocumentSets() as $documentSet) {
75
            /** @var DocumentSet $documentSet */
76
            $documents->merge($documentSet->getDocuments());
77
        }
78
        $documents->removeDuplicates();
79
80
        return $documents;
81
    }
82
83
    public function onBeforeDelete()
84
    {
85
        if (Versioned::current_stage() == 'Live') {
86
            $existsOnOtherStage = !$this->owner->getIsDeletedFromStage();
87
        } else {
88
            $existsOnOtherStage = $this->owner->getExistsOnLive();
0 ignored issues
show
Bug introduced by
The method getExistsOnLive() does not exist on SS_Object. Did you maybe mean exists()?

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

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

Loading history...
89
        }
90
91
        // Only remove if record doesn't still exist on live stage.
92
        if (!$existsOnOtherStage) {
93
            $dmsDocuments = $this->owner->getAllDocuments();
94
            foreach ($dmsDocuments as $document) {
95
                // If the document is only associated with one page, i.e. only associated with this page
96
                if ($document->getRelatedPages()->count() <= 1) {
97
                    // Delete the document before deleting this page
98
                    $document->delete();
99
                }
100
            }
101
        }
102
    }
103
104
    public function onBeforePublish()
105
    {
106
        $embargoedDocuments = $this->owner->getAllDocuments()->filter('EmbargoedUntilPublished', true);
107
        if ($embargoedDocuments->count() > 0) {
108
            foreach ($embargoedDocuments as $doc) {
109
                $doc->EmbargoedUntilPublished = false;
110
                $doc->write();
111
            }
112
        }
113
    }
114
115
    /**
116
     * Returns the title of the page with the total number of documents it has associated with it across
117
     * all document sets
118
     *
119
     * @return string
120
     */
121
    public function getTitleWithNumberOfDocuments()
122
    {
123
        return $this->owner->Title . ' (' . $this->owner->getAllDocuments()->count() . ')';
0 ignored issues
show
Bug introduced by
The property Title does not seem to exist in SS_Object.

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

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

Loading history...
124
    }
125
}
126