This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
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 combination product combines several products into one new product. |
||
4 | * |
||
5 | * The way this works is that the combo product links to zero or more products (many many relationship) |
||
6 | * |
||
7 | * When you add the combo product, the individual products are added. A modifier adds the "discount" for the combo. |
||
8 | * It also deletes all the products as soon as you delete one. |
||
9 | * |
||
10 | * There are two restrictions to keep in mind: |
||
11 | * (a) it only applies to products and not all buyables. |
||
12 | * (b) all products need to return true for canPurchase. This means that if the product is available as part of a combo, it should also be available by itself. |
||
13 | * |
||
14 | * We use the sort order for the order attribute to group it... |
||
15 | * |
||
16 | * @package: ecommerce |
||
17 | * @sub-package: products |
||
18 | * |
||
19 | **/ |
||
20 | |||
21 | |||
22 | class CombinationProduct extends Product |
||
0 ignored issues
–
show
|
|||
23 | { |
||
24 | private static $db = array( |
||
0 ignored issues
–
show
|
|||
25 | 'NewPrice' => 'Currency' |
||
26 | ); |
||
27 | |||
28 | private static $many_many = array( |
||
0 ignored issues
–
show
|
|||
29 | 'IncludedProducts' => 'Product' |
||
30 | ); |
||
31 | |||
32 | private static $searchable_fields = array( |
||
0 ignored issues
–
show
|
|||
33 | 'ID', |
||
34 | 'Title', |
||
35 | 'InternalItemID', |
||
36 | 'Price', |
||
37 | 'ListOfProducts' |
||
38 | ); |
||
39 | |||
40 | private static $casting = array( |
||
0 ignored issues
–
show
|
|||
41 | "OriginalPrice" => "Currency" |
||
42 | ); |
||
43 | |||
44 | private static $singular_name = "Combination Product"; |
||
0 ignored issues
–
show
|
|||
45 | public function i18n_singular_name() |
||
46 | { |
||
47 | return _t("CombinationProduct.COMBINATIONPRODUCT", "Combination Product"); |
||
48 | } |
||
49 | |||
50 | private static $plural_name = "Combination Products"; |
||
0 ignored issues
–
show
|
|||
51 | public function i18n_plural_name() |
||
52 | { |
||
53 | return _t("CombinationProduct.COMBINATIONPRODUCTS", "Combination Products"); |
||
54 | } |
||
55 | |||
56 | private static $default_parent = 'ProductGroup'; |
||
0 ignored issues
–
show
|
|||
57 | |||
58 | private static $default_sort = '"Title" ASC'; |
||
0 ignored issues
–
show
|
|||
59 | |||
60 | private static $icon = 'ecommerce_combo_product/images/icons/CombinationProduct'; |
||
0 ignored issues
–
show
|
|||
61 | |||
62 | public function getCMSFields() |
||
0 ignored issues
–
show
The return type could not be reliably inferred; please add a
@return annotation.
Our type inference engine in quite powerful, but sometimes the code does not
provide enough clues to go by. In these cases we request you to add a ![]() |
|||
63 | { |
||
64 | $fields = parent::getCMSFields(); |
||
65 | $fields->addFieldToTab("Root.Components", $this->getIncludedProductsFormField()); |
||
66 | $fields->replaceField("Price", new ReadOnlyField("Price", "Full Price")); |
||
67 | $fields->addFieldToTab("Root.Details", new NumericField("NewPrice", "New Price"), "Price"); |
||
68 | $fields->addFieldToTab("Root.Details", new ReadOnlyField("Savings", "Savings", $this->getPrice() - $this->NewPrice), "Price"); |
||
69 | return $fields; |
||
70 | } |
||
71 | |||
72 | |||
73 | /** |
||
74 | *@return TreeMultiselectField |
||
75 | **/ |
||
76 | protected function getIncludedProductsFormField() |
||
77 | { |
||
78 | $field = new TreeMultiselectField( |
||
79 | $name = "IncludedProducts", |
||
80 | $title = "Included Products", |
||
81 | $sourceObject = "SiteTree", |
||
82 | $keyField = "ID", |
||
83 | $labelField = "MenuTitle" |
||
84 | ); |
||
85 | $filter = create_function('$obj', 'return ( ( $obj InstanceOf Product || $obj InstanceOf ProductGroup) && ($obj->ID != '.$this->ID.'));'); |
||
0 ignored issues
–
show
The use of
create_function is highly discouraged, better use a closure.
// Instead of
$function = create_function('$a, $b', 'return $a + $b');
// Better use
$function = function($a, $b) { return $a + $b; }
![]() |
|||
86 | $field->setFilterFunction($filter); |
||
87 | return $field; |
||
88 | } |
||
89 | |||
90 | /** |
||
91 | * Conditions for whether a product can be purchased. |
||
92 | * |
||
93 | * If it has the checkbox for 'Allow this product to be purchased', |
||
94 | * as well as having a price, it can be purchased. Otherwise a user |
||
95 | * can't buy it. |
||
96 | * |
||
97 | * Other conditions may be added by decorating with the canPurcahse function |
||
98 | * |
||
99 | * @return boolean |
||
100 | */ |
||
101 | public function canPurchase(Member $member = null, $checkPrice = true) |
||
102 | { |
||
103 | if ($includedProducts = $this->IncludedProducts()) { |
||
104 | if ($includedProducts->count()) { |
||
105 | foreach ($includedProducts as $includedProduct) { |
||
106 | if (!$includedProduct->canPurchase($member)) { |
||
107 | return false; |
||
108 | } |
||
109 | } |
||
110 | return parent::canPurchase($member); |
||
111 | } |
||
112 | } |
||
113 | return false; |
||
114 | } |
||
115 | |||
116 | public function classNameForOrderItem() |
||
117 | { |
||
118 | return "CombinationProduct_OrderItem"; |
||
119 | } |
||
120 | |||
121 | |||
122 | /** |
||
123 | * |
||
124 | * |
||
125 | * |
||
126 | */ |
||
127 | public function getPrice() |
||
128 | { |
||
129 | if ($includedProducts = $this->IncludedProducts()) { |
||
130 | $originalPrice = 0; |
||
131 | if ($includedProducts && $includedProducts->count()) { |
||
132 | foreach ($includedProducts as $includedProduct) { |
||
133 | $originalPrice += $includedProduct->CalculatedPrice(); |
||
134 | } |
||
135 | } |
||
136 | } |
||
137 | return $originalPrice; |
||
0 ignored issues
–
show
The variable
$originalPrice does not seem to be defined for all execution paths leading up to this point.
If you define a variable conditionally, it can happen that it is not defined for all execution paths. Let’s take a look at an example: function myFunction($a) {
switch ($a) {
case 'foo':
$x = 1;
break;
case 'bar':
$x = 2;
break;
}
// $x is potentially undefined here.
echo $x;
}
In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined. Available Fixes
![]() |
|||
138 | } |
||
139 | |||
140 | public function getCalculatedPrice() |
||
0 ignored issues
–
show
The return type could not be reliably inferred; please add a
@return annotation.
Our type inference engine in quite powerful, but sometimes the code does not
provide enough clues to go by. In these cases we request you to add a ![]() |
|||
141 | { |
||
142 | return $this->getField("NewPrice"); |
||
143 | } |
||
144 | |||
145 | /** |
||
146 | * remove any non-products from the list. |
||
147 | * |
||
148 | */ |
||
149 | public function onBeforeWrite() |
||
150 | { |
||
151 | parent::onBeforeWrite(); |
||
152 | $includedProducts = $this->IncludedProducts(); |
||
153 | if ($includedProducts) { |
||
154 | foreach ($includedProducts as $includedProduct) { |
||
155 | if (!$includedProduct instanceof Product) { |
||
156 | $includedProducts->remove($includedProduct); |
||
157 | } |
||
158 | } |
||
159 | } |
||
160 | $this->Price = $this->NewPrice; |
||
161 | } |
||
162 | } |
||
163 | |||
164 | class CombinationProduct_Controller extends Product_Controller |
||
0 ignored issues
–
show
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. ![]() |
|||
165 | { |
||
166 | public function init() |
||
167 | { |
||
168 | parent::init(); |
||
169 | Requirements::themedCSS("CombinationProduct", "ecommerce_combo_product"); |
||
170 | } |
||
171 | } |
||
172 | |||
173 | |||
174 | class CombinationProduct_OrderItem extends Product_OrderItem |
||
0 ignored issues
–
show
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. ![]() |
|||
175 | { |
||
176 | |||
177 | |||
178 | //add a deletion system |
||
179 | |||
180 | public function onBeforeDelete() |
||
181 | { |
||
182 | parent::onBeforeDelete(); |
||
183 | $includedProductsOrderItems = IncludedProduct_OrderItem::get() |
||
184 | ->filter(array("ParentOrderItemID" => $this->ID, "OrderID" => $this->Order()->ID)); |
||
185 | if ($includedProductsOrderItems->count()) { |
||
186 | foreach ($includedProductsOrderItems as $includedProductsOrderItem) { |
||
187 | $includedProductsOrderItem->delete(); |
||
188 | $includedProductsOrderItem->destroy(); |
||
189 | } |
||
190 | } |
||
191 | } |
||
192 | |||
193 | public function TableSubTitle() |
||
194 | { |
||
195 | $buyable = $this->Buyable(); |
||
196 | $includedProducts = $buyable->IncludedProducts(); |
||
197 | $titleArray = array(); |
||
198 | if ($includedProducts) { |
||
199 | foreach ($includedProducts as $includedProduct) { |
||
200 | $titleArray[] = $includedProduct->MenuTitle; |
||
201 | } |
||
202 | } |
||
203 | if (count($titleArray)) { |
||
204 | return _t("CombinationProduct.INCLUDES", "Includes").": ".implode(", ", $titleArray)."."; |
||
205 | } |
||
206 | } |
||
207 | |||
208 | public function onBeforeWrite() |
||
209 | { |
||
210 | parent::onBeforeWrite(); |
||
211 | $this->Sort = $this->Buyable()->ID; |
||
0 ignored issues
–
show
The property
Sort does not exist on object<CombinationProduct_OrderItem> . Since you implemented __set , maybe consider adding a @property annotation.
Since your code implements the magic setter <?php
/**
* @property int $x
* @property int $y
* @property string $text
*/
class MyLabel
{
private $properties;
private $allowedProperties = array('x', 'y', 'text');
public function __get($name)
{
if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
return $properties[$name];
} else {
return null;
}
}
public function __set($name, $value)
{
if (in_array($name, $this->allowedProperties)) {
$properties[$name] = $value;
} else {
throw new \LogicException("Property $name is not defined.");
}
}
}
Since the property has write access only, you can use the @property-write annotation instead. Of course, you may also just have mistyped another name, in which case you should fix the error. See also the PhpDoc documentation for @property. ![]() |
|||
212 | } |
||
213 | } |
||
214 | |||
215 | class IncludedProduct_OrderItem extends Product_OrderItem |
||
0 ignored issues
–
show
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. ![]() |
|||
216 | { |
||
217 | private static $has_one = array( |
||
0 ignored issues
–
show
|
|||
218 | "ParentOrderItem" => "CombinationProduct_OrderItem" |
||
219 | ); |
||
220 | |||
221 | public function LiveCalculatedTotal() |
||
222 | { |
||
223 | return 0; |
||
224 | } |
||
225 | |||
226 | public function Total($recalculate = false) |
||
227 | { |
||
228 | return $this->getTotal($recalculate); |
||
229 | } |
||
230 | |||
231 | public function getTotal($recalculate = false) |
||
232 | { |
||
233 | return 0; |
||
234 | } |
||
235 | |||
236 | public function TableSubTitle() |
||
237 | { |
||
238 | Requirements::themedCSS("CombinationProductModifier", "ecommerce_combo_product"); |
||
239 | return _t("CombinationProduct.PARTOF", "Part of").": ".$this->ParentOrderItem()->TableTitle()."."; |
||
0 ignored issues
–
show
The method
ParentOrderItem does not exist on object<IncludedProduct_OrderItem> ? Since you implemented __call , maybe consider adding a @method annotation.
If you implement This is often the case, when 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 { }
![]() |
|||
240 | } |
||
241 | |||
242 | public function onBeforeWrite() |
||
243 | { |
||
244 | parent::onBeforeWrite(); |
||
245 | if ($parentOrderItem = $this->ParentOrderItem()) { |
||
0 ignored issues
–
show
The method
ParentOrderItem does not exist on object<IncludedProduct_OrderItem> ? Since you implemented __call , maybe consider adding a @method annotation.
If you implement This is often the case, when 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 { }
![]() |
|||
246 | if ($buyable = $parentOrderItem->Buyable()) { |
||
247 | $this->Sort = $buyable->ID + 1; |
||
0 ignored issues
–
show
The property
Sort does not exist on object<IncludedProduct_OrderItem> . Since you implemented __set , maybe consider adding a @property annotation.
Since your code implements the magic setter <?php
/**
* @property int $x
* @property int $y
* @property string $text
*/
class MyLabel
{
private $properties;
private $allowedProperties = array('x', 'y', 'text');
public function __get($name)
{
if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
return $properties[$name];
} else {
return null;
}
}
public function __set($name, $value)
{
if (in_array($name, $this->allowedProperties)) {
$properties[$name] = $value;
} else {
throw new \LogicException("Property $name is not defined.");
}
}
}
Since the property has write access only, you can use the @property-write annotation instead. Of course, you may also just have mistyped another name, in which case you should fix the error. See also the PhpDoc documentation for @property. ![]() |
|||
248 | } |
||
249 | } |
||
250 | } |
||
251 | |||
252 | public function RemoveLink() |
||
253 | { |
||
254 | return ""; |
||
255 | } |
||
256 | |||
257 | |||
258 | public function RemoveAllLink() |
||
259 | { |
||
260 | return ""; |
||
261 | } |
||
262 | |||
263 | public function QuantityField() |
||
264 | { |
||
265 | return new ReadonlyField("Quantity", "", $this->Quantity); |
||
0 ignored issues
–
show
The property
Quantity does not exist on object<IncludedProduct_OrderItem> . Since you implemented __get , maybe consider adding a @property annotation.
Since your code implements the magic getter <?php
/**
* @property int $x
* @property int $y
* @property string $text
*/
class MyLabel
{
private $properties;
private $allowedProperties = array('x', 'y', 'text');
public function __get($name)
{
if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
return $properties[$name];
} else {
return null;
}
}
public function __set($name, $value)
{
if (in_array($name, $this->allowedProperties)) {
$properties[$name] = $value;
} else {
throw new \LogicException("Property $name is not defined.");
}
}
}
If the property has read access only, you can use the @property-read annotation instead. Of course, you may also just have mistyped another name, in which case you should fix the error. See also the PhpDoc documentation for @property. ![]() |
|||
266 | } |
||
267 | |||
268 | |||
269 | public function onBeforeDelete() |
||
270 | { |
||
271 | parent::onBeforeDelete(); |
||
272 | CartResponse::set_force_reload(); |
||
273 | } |
||
274 | } |
||
275 |
You can fix this by adding a namespace to your class:
When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.