Issues (199)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

code/classes/DMSDocumentCart.php (6 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
 * Class DMSDocumentCart represents the shopping cart.
4
 *
5
 */
6
class DMSDocumentCart extends ViewableData
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
7
{
8
    /**
9
     * A handle to the classes' {@link DMSCartBackendInterface}
10
     *
11
     * @var DMSCartBackendInterface
12
     */
13
    protected $backend;
14
15
    /**
16
     * Variable to control whether a cart is being updated or not
17
     *
18
     * @var bool
19
     */
20
    private $viewOnly = false;
21
22
    /**
23
     * Instantiate a cart backend either by that provided, or a session default
24
     *
25
     * @param DMSCartBackendInterface $backend
0 ignored issues
show
Should the type for parameter $backend not be DMSCartBackendInterface|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...
26
     * @throws DMSDocumentCartException If a backend was provided but doesn't implement the backend interface
27
     */
28
    public function __construct($backend = null)
29
    {
30
        parent::__construct();
31
        if ($backend && !($backend instanceof DMSCartBackendInterface)) {
32
            throw new DMSDocumentCartException('Backend must implement DMSCartBackendInterface!');
33
        }
34
        $this->backend = ($backend) ?: DMSSessionBackend::singleton();
35
    }
36
37
    /**
38
     * Returns all the cart items as an array
39
     *
40
     * @return ArrayList
41
     */
42
    public function getItems()
43
    {
44
        $validItems = ArrayList::create();
45
        foreach ($this->backend->getItems() as $item) {
46
            /** @var DMSRequestItem $item */
47
            if (!$item->getDocument()) {
48
                $this->backend->removeItem($item);
49
                continue;
50
            }
51
            $validItems->push($item);
52
        }
53
        return $validItems;
54
    }
55
56
    /**
57
     * Gets a partial caching key that can be used to prevent the getItems method from hitting the database every
58
     * time to check whether a document exists. Includes a hash of the valid items in the cart (including their
59
     * quantity).
60
     *
61
     * @return string
62
     */
63
    public function getCartSummaryCacheKey()
64
    {
65
        return 'dms-cart-items-' . md5(serialize($this->getItems()));
66
    }
67
68
    /**
69
     * Add an {@link DMSRequestItem} object into the cart.
70
     *
71
     * @param DMSRequestItem $item
72
     *
73
     * @return DMSDocumentCart
74
     */
75
    public function addItem(DMSRequestItem $item)
76
    {
77
        $this->backend->addItem($item);
78
79
        return $this;
80
    }
81
82
    /**
83
     * Get a {@link DMSRequestItem} object from the cart.
84
     *
85
     * @param int $itemID The ID of the item
86
     *
87
     * @return DMSRequestItem|boolean
88
     */
89
    public function getItem($itemID)
90
    {
91
        return $this->backend->getItem($itemID);
92
    }
93
94
    /**
95
     * Removes a {@link DMSRequestItem} from the cart by it's id
96
     *
97
     * @param DMSRequestItem $item
98
     *
99
     * @return DMSDocumentCart
100
     */
101
    public function removeItem(DMSRequestItem $item)
102
    {
103
        $this->backend->removeItem($item);
104
105
        return $this;
106
    }
107
108
    /**
109
     * Removes a {@link DMSRequestItem} from the cart by it's id
110
     *
111
     * @param int $itemID
112
     *
113
     * @return DMSDocumentCart
114
     */
115
    public function removeItemByID($itemID)
116
    {
117
        $this->backend->removeItemByID($itemID);
118
119
        return $this;
120
    }
121
122
    /**
123
     * Adjusts (increments, decrements or amends) the quantity of an {@link DMSRequestItem}.'
124
     * A positive $quantity increments the total, whereas a negative value decrements the total. A cart item
125
     * is removed completely if it's value reaches <= 0.
126
     *
127
     * @param int $itemID
128
     * @param int $quantity
129
     *
130
     * @return DMSDocumentCart
131
     */
132
    public function updateItemQuantity($itemID, $quantity)
133
    {
134
        if ($item = $this->getItem($itemID)) {
135
            $currentQuantity = $item->getQuantity();
136
            $newQuantity = $currentQuantity + $quantity;
137
            if ($newQuantity <= 0) {
138
                $this->removeItemByID($itemID);
139
            } else {
140
                $item->setQuantity($newQuantity);
141
                $this->addItem($item);
0 ignored issues
show
It seems like $item defined by $this->getItem($itemID) on line 134 can also be of type boolean; however, DMSDocumentCart::addItem() does only seem to accept object<DMSRequestItem>, 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...
142
            }
143
        }
144
145
        return $this;
146
    }
147
148
    /**
149
     * Completely empties a cart
150
     *
151
     * @return DMSDocumentCart
152
     */
153
    public function emptyCart()
154
    {
155
        $this->backend->emptyCart();
156
157
        return $this;
158
    }
159
160
    /**
161
     * Checks if a cart is empty.
162
     * Returns true if cart is empty, false otherwise.
163
     *
164
     * @return boolean
165
     */
166
    public function isCartEmpty()
167
    {
168
        $items = $this->getItems();
169
170
        return !$items->exists();
171
    }
172
173
    /**
174
     * Set the backURL to be a Session variable for the current Document Cart
175
     *
176
     * @param string $backURL
177
     *
178
     * @return DMSDocumentCart
179
     */
180
    public function setBackUrl($backURL)
181
    {
182
        $this->backend->setBackUrl($backURL);
183
184
        return $this;
185
    }
186
187
    /**
188
     * Returns the backURL for the current Document Cart
189
     *
190
     * @return string
191
     */
192
    public function getBackUrl()
193
    {
194
        return $this->backend->getBackUrl();
195
    }
196
197
    /**
198
     * Sets the recipients info as an array (e.g. array('Name'=>'Joe','Surname'=>'Soap'))
199
     *
200
     * @param array $receiverInfo
201
     *
202
     * @return DMSDocumentCart
203
     */
204
    public function setReceiverInfo($receiverInfo)
205
    {
206
        $this->backend->setReceiverInfo($receiverInfo);
207
208
        return $this;
209
    }
210
211
    /**
212
     * Retrieves the recipients info as an array (e.g. array('Name'=>'Joe','Surname'=>'Soap'))
213
     *
214
     * @return array
215
     */
216
    public function getReceiverInfo()
217
    {
218
        return $this->backend->getReceiverInfo();
219
    }
220
221
    /**
222
     * Returns the recipients in a Viewable format
223
     *
224
     * @return ArrayData|bool
225
     */
226
    public function getReceiverInfoNice()
227
    {
228
        return (is_array($this->getReceiverInfo())) ? ArrayData::create($this->getReceiverInfo()) : false;
229
    }
230
231
    /**
232
     * Gets the backend handler
233
     *
234
     * @return DMSSessionBackend
235
     */
236
    public function getBackend()
237
    {
238
        return $this->backend;
239
    }
240
241
    /**
242
     * Checks if an item exists within a cart. Returns true (if exists) or false.
243
     *
244
     * @param int $itemID
245
     *
246
     * @return bool
247
     */
248
    public function isInCart($itemID)
249
    {
250
        return (bool) $this->getItem($itemID);
251
    }
252
253
    /**
254
     * Persists a cart submission to the database
255
     *
256
     * @param Form $form
257
     *
258
     * @return int
259
     */
260
    public function saveSubmission(Form $form)
261
    {
262
        $submission = DMSDocumentCartSubmission::create();
263
        $form->saveInto($submission);
264
        $return = $submission->write();
265
        $this->getItems()->each(function ($item) use ($submission) {
266
            /** @var DMSDocument $document */
267
            $document = $item->getDocument();
268
            $submissionItem = DMSDocumentCartSubmissionItem::create(array(
269
                'OriginalID' => $document->ID,
270
                'Quantity' => $item->getQuantity(),
271
                'Title' => $document->getTitle(),
272
                'Filename' => $document->getFilenameWithoutID()
273
            ));
274
            $submission->Items()->add($submissionItem);
0 ignored issues
show
Documentation Bug introduced by
The method Items does not exist on object<DMSDocumentCartSubmission>? 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...
275
            $document->incrementPrintRequest();
276
        });
277
278
        return $return;
279
    }
280
281
    /**
282
     * Returns true if the cart is being updated. False otherwise
283
     * @return bool
284
     */
285
    public function isViewOnly()
286
    {
287
        return $this->viewOnly;
288
    }
289
290
    /**
291
     * Sets the updating flag
292
     *
293
     * @param bool $viewOnly
294
     * @return DMSDocumentCart
295
     */
296
    public function setViewOnly($viewOnly)
297
    {
298
        $this->viewOnly = (bool) $viewOnly;
299
        return $this;
300
    }
301
302
    /**
303
     * Displays a view-only table of the cart items.
304
     *
305
     * @return HTMLText
306
     */
307
    public function getSummary()
308
    {
309
        return $this->renderWith('DMSDocumentCartSummary');
310
    }
311
312
    /**
313
     * Utility method to link to the current controllers action
314
     *
315
     * @param string $action
0 ignored issues
show
Should the type for parameter $action not be string|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...
316
     * @return string
0 ignored issues
show
Should the return type not be string|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
317
     */
318
    public function getLink($action = null)
319
    {
320
        return DMSDocumentCartController::create()->Link($action);
321
    }
322
}
323