ProductQuestionsAnswerNOHTML()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
3
/**
4
 * adds functionality to OrderItems.
5
 */
6
class ProductQuestion_OrderItemExtension extends DataExtension
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
    private static $db = array(
0 ignored issues
show
Unused Code introduced by
The property $db is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
9
        'ProductQuestionsAnswer' => 'HTMLText',
10
        'JSONAnswers' => 'Text',
11
    );
12
13
    private static $casting = array(
0 ignored issues
show
Unused Code introduced by
The property $casting is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
14
        'ProductQuestionsAnswerNOHTML' => 'Text',
15
        'ConfigureLabel' => 'Varchar',
16
        'ConfigureLink' => 'Varchar',
17
    );
18
19
    public function updateCMSFields(FieldList $fields)
20
    {
21
        $fields->addFieldsToTab(
22
            'Root.Questions',
23
            array(
24
                ReadOnlyField::create('ProductQuestionsAnswer', _t('ProductQuestions.ANSWERS', 'Answers')),
25
                ReadOnlyField::create('JSONAnswers', _t('ProductQuestions.JSON_ANSWERS', 'Answers as JSON')),
26
            )
27
        );
28
        return $fields;
29
    }
30
31
    /**
32
     * @return bool
33
     */
34 View Code Duplication
    public function AllQuestionsAnswered()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
35
    {
36
        if ($answers = $this->owner->ProductQuestionsAnswers()) {
37
            foreach ($answers as $productQuestion) {
38
                if (!$productQuestion->Answer) {
39
                    return false;
40
                }
41
            }
42
        }
43
44
        return true;
45
    }
46
47
    /**
48
     * @return bool
49
     */
50 View Code Duplication
    public function AllRequiredQuestionsAnswered()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
51
    {
52
        if ($answers = $this->owner->ProductQuestionsAnswers()) {
53
            foreach ($answers as $productQuestion) {
54
                if ($productQuestion->AnswerRequired) {
55
                    if (!$productQuestion->Answer) {
56
                        return false;
57
                    }
58
                }
59
            }
60
        }
61
62
        return true;
63
    }
64
65
    /**
66
     * casted variable.
67
     *
68
     * @return string
69
     */
70
    public function ProductQuestionsAnswerNOHTML()
71
    {
72
        return $this->owner->getProductQuestionsAnswerNOHTML();
73
    }
74
75
    public function getProductQuestionsAnswerNOHTML()
76
    {
77
        return strip_tags($this->owner->ProductQuestionsAnswer);
0 ignored issues
show
Bug introduced by
The property ProductQuestionsAnswer 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...
78
    }
79
80
    /**
81
     * can the order item be configured.
82
     *
83
     * @return bool
84
     */
85
    public function canConfigure()
86
    {
87
        if ($this->owner->Order()->IsSubmitted()) {
0 ignored issues
show
Unused Code introduced by
This if statement, and the following return statement can be replaced with return !$this->owner->Order()->IsSubmitted();.
Loading history...
88
            return false;
89
        }
90
91
        return true;
92
    }
93
94
    /**
95
     * can the order item be configured.
96
     *
97
     * @return bool
98
     */
99
    public function HasRequiredQuestions()
100
    {
101
        if ($this->owner->AllRequiredQuestionsAnswered()) {
0 ignored issues
show
Unused Code introduced by
This if statement, and the following return statement can be replaced with return !$this->owner->Al...redQuestionsAnswered();.
Loading history...
102
            return false;
103
        }
104
105
        return true;
106
    }
107
108
    /**
109
     * returns a link to configure an OrderItem
110
     * and adds the relevant requirements.
111
     *
112
     * @return string
113
     */
114
    public function ConfigureLabel()
115
    {
116
        Requirements::javascript('ecommerce_product_questions/javascript/EcomProductQuestions.js');
117
118
        return $this->owner->ProductQuestionsAnswerFormLabel();
119
    }
120
121
    /**
122
     * returns a link to configure an OrderItem
123
     * and adds the relevant requirements.
124
     *
125
     * @return string
126
     */
127
    public function ConfigureLink()
128
    {
129
        Requirements::javascript('ecommerce_product_questions/javascript/EcomProductQuestions.js');
130
131
        return $this->owner->ProductQuestionsAnswerFormLink();
132
    }
133
134
    /**
135
     * returns the link to edit the products.
136
     *
137
     * @return string
138
     */
139
    public function ProductQuestionsAnswerFormLabel()
140
    {
141
        if ($this->owner->HasProductQuestions()) {
142
            $buyable = $this->productQuestionBuyable();
143
            if ($buyable) {
144
                if ($label = $buyable->CustomConfigureLabel()) {
145
                    return $label;
146
                }
147
            }
148
149
            return _t('ProductQuestion.CONFIGURE', 'Configure');
150
        }
151
152
        return '';
153
    }
154
155
    /**
156
     * returns the link to edit the products.
157
     *
158
     * @return string
159
     */
160
    public function ProductQuestionsAnswerFormLink()
161
    {
162
        if ($this->owner->HasProductQuestions()) {
163
            $buyable = $this->productQuestionBuyable();
164
            if ($buyable) {
165
                return $buyable->ProductQuestionsAnswerFormLink($this->owner->ID);
0 ignored issues
show
Bug introduced by
The property ID 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...
166
            }
167
        }
168
169
        return '';
170
    }
171
172
    /**
173
     * cache only!
174
     *
175
     * @var array
176
     */
177
    private static $_has_product_questions = array();
178
179
    /**
180
     * Does the buyable associated with the orderitem
181
     * have product questions?
182
     *
183
     * @return bool
184
     */
185 View Code Duplication
    public function HasProductQuestions()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
186
    {
187
        if (!isset(self::$_has_product_questions[$this->owner->ID])) {
188
            $productQuestions = $this->owner->ProductQuestions();
189
            if ($productQuestions && $productQuestions->count()) {
190
                self::$_has_product_questions[$this->owner->ID] = true;
0 ignored issues
show
Bug introduced by
The property ID 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...
191
            } else {
192
                self::$_has_product_questions[$this->owner->ID] = false;
193
            }
194
        }
195
196
        return self::$_has_product_questions[$this->owner->ID];
197
    }
198
199
    /**
200
     * cache only!
201
     *
202
     * @var array
203
     */
204
    private static $_product_questions = array();
205
206
    /**
207
     * @alias for ProductQuestions
208
     */
209
    public function ApplicableProductQuestions()
210
    {
211
        return $this->ProductQuestions();
212
    }
213
214
    /**
215
     * @return DataList | Null
216
     */
217 View Code Duplication
    public function ProductQuestions()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
218
    {
219
        if (!isset(self::$_product_questions[$this->owner->ID])) {
220
            if ($buyable = $this->owner->productQuestionBuyable()) {
221
                self::$_product_questions[$this->owner->ID] = $buyable->ApplicableProductQuestions();
0 ignored issues
show
Bug introduced by
The property ID 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...
222
            } else {
223
                self::$_product_questions[$this->owner->ID] = null;
224
            }
225
        }
226
227
        return self::$_product_questions[$this->owner->ID];
228
    }
229
230
    /**
231
     * cache only!
232
     *
233
     * @var array
234
     */
235
    private static $_product_question_product = null;
236
237
    /**
238
     * @return Product | Null
239
     */
240
    public function productQuestionBuyable()
241
    {
242
        if (!isset(self::$_product_question_product[$this->owner->ID])) {
243
            self::$_product_question_product[$this->owner->ID] = $this->owner->Buyable();
0 ignored issues
show
Bug introduced by
The property ID 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...
244
        }
245
246
        return self::$_product_question_product[$this->owner->ID];
247
    }
248
249
    /**
250
     *
251
     * @return Form
252
     */
253
    public function ProductQuestionsAnswerFormInCheckoutPage()
254
    {
255
        return ModelAsController::controller_for($this->owner->Buyable())->ProductQuestionsAnswerForm($this->owner);
256
    }
257
258
    /**
259
     * @return Form
0 ignored issues
show
Documentation introduced by
Should the return type not be Form|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...
260
     */
261
    public function ProductQuestionsAnswerForm($controller = null, $name = 'productquestionsanswerselect')
0 ignored issues
show
Coding Style introduced by
ProductQuestionsAnswerForm uses the super-global variable $_GET which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
262
    {
263
        $productQuestions = $this->owner->ProductQuestions();
264
        $buyable = $this->productQuestionBuyable();
265
        $backURL = Session::get('BackURL');
266
        if ($backURL || empty($_GET['BackURL'])) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
267
            //do nothing
268
        } else {
269
            $backURL = $_GET['BackURL'];
270
        }
271
        if ($productQuestions && $productQuestions->count()) {
272
            $requiredfields = array();
273
            $fields = new FieldList(
274
                new HiddenField('OrderItemID', 'OrderItemID', $this->owner->ID),
0 ignored issues
show
Bug introduced by
The property ID 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...
275
                new HiddenField('BackURL', 'BackURL', $backURL)
276
            );
277
            $values = array();
278
            if ($this->owner->JSONAnswers) {
279
                $values = json_decode($this->owner->JSONAnswers);
0 ignored issues
show
Bug introduced by
The property JSONAnswers 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...
280
            }
281
            foreach ($productQuestions as $productQuestion) {
282
                $value = empty($values->{$productQuestion->ID}) ? null : $values->{$productQuestion->ID};
283
                $fields->push($productQuestion->getFieldForProduct($buyable, $value)); //TODO: perhaps use a dropdown instead (eliminates need to use keyboard)
284
            }
285
            $actions = new FieldList(
286
                array(
287
                    new FormAction('addproductquestionsanswer', _t('ProductQuestion.ANSWER_QUESTION', 'Update Selection')),
288
                )
289
            );
290
            $validator = new RequiredFields($requiredfields);
291
            $form = new Form($controller, $name, $fields, $actions, $validator);
292
            Requirements::themedCSS('Cart');
293
294
            return $form;
295
        }
296
    }
297
298
    /**
299
     * @return ArrayList | NULL
0 ignored issues
show
Documentation introduced by
Should the return type not be ArrayList|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...
300
     */
301
    public function ProductQuestionsAnswers()
302
    {
303
        if ($this->owner->HasProductQuestions()) {
304
            $al = new ArrayList();
305
            $values = json_decode($this->owner->JSONAnswers);
0 ignored issues
show
Bug introduced by
The property JSONAnswers 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...
306
            if ($questions = $this->owner->ProductQuestions()) {
307
                foreach ($questions as $question) {
308
                    $newQuestion = clone $question;
309
                    $answer = empty($values->{$question->ID}) ? null : $values->{$question->ID};
310
                    if ($answer) {
311
                        $newQuestion->Answer = $answer;
312
                    } elseif ($newQuestion->AnswerRequired) {
313
                        $newQuestion->Answer = null;
314
                    } else {
315
                        $newQuestion->Answer = $newQuestion->DefaultAnswer;
316
                    }
317
                    $al->push($newQuestion);
318
                }
319
320
                return $al;
321
            }
322
        }
323
    }
324
325
    /**
326
     * @param array $answers
327
     *                       ID = ProductQuestion.ID
328
     *                       "ID" => "Answer" (String)
329
     * @param bool  $write
330
     */
331
    public function updateOrderItemWithProductAnswers($answers, $write = true)
332
    {
333
        if ($this->owner->canEdit()) {
334
            $this->owner->ProductQuestionsAnswer = '';
0 ignored issues
show
Bug introduced by
The property ProductQuestionsAnswer 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...
335
            if (is_array($answers) && count($answers)) {
336
                foreach ($answers as $productQuestionID => $productQuestionAnswer) {
337
                    $question = ProductQuestion::get()->byID(intval($productQuestionID));
338
                    if ($question) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
339
                    }
340
                    //$form->addErrorMessage("ProductQuestions", $message, $type);
0 ignored issues
show
Unused Code Comprehensibility introduced by
77% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
341
                }
342
                $this->owner->ProductQuestionsAnswer = $this->owner->renderWith('ProductQuestionsAnswers')->getValue();
343
            }
344
            $this->owner->JSONAnswers = json_encode($answers);
0 ignored issues
show
Bug introduced by
The property JSONAnswers 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...
345
            if ($write) {
346
                $this->owner->write();
347
            }
348
        }
349
    }
350
351
    public function onBeforeWrite()
352
    {
353
        parent::onBeforeWrite();
354
        if (!empty($this->owner->Parameters)) {
355
            if (!empty($this->owner->Parameters['productquestions'])) {
356
                $answers = array();
357
                $params = $this->owner->Parameters['productquestions'];
0 ignored issues
show
Bug introduced by
The property Parameters 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...
358
                $params = urldecode($params);
359
                $items = explode('|', $params);
360
                if ($items && is_array($items) && count($items)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $items of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
361
                    foreach ($items as $item) {
362
                        if ($item) {
363
                            $itemArray = explode('=', $item);
364
                            if (is_array($itemArray) && count($itemArray) == 2) {
365
                                $key = intval(str_replace(array('ProductQuestions[', ']'), '', $itemArray[0]));
366
                                $value = convert::raw2sql($itemArray[1]);
367
                                $answers[$key] = $value;
368
                            }
369
                        }
370
                    }
371
                }
372
                unset($this->owner->Parameters);
373
                $this->updateOrderItemWithProductAnswers($answers, false);
374
            }
375
        }
376
    }
377
}
378