GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — develop ( 080777...9cdac9 )
by Stuart
07:21
created

BaseElementAction::isPluralTarget()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 15
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
dl 0
loc 15
rs 9.4286
c 1
b 0
f 0
cc 3
eloc 6
nc 3
nop 1
1
<?php
2
3
/**
4
 * Copyright (c) 2011-present Mediasift Ltd
5
 * All rights reserved.
6
 *
7
 * Redistribution and use in source and binary forms, with or without
8
 * modification, are permitted provided that the following conditions
9
 * are met:
10
 *
11
 *   * Redistributions of source code must retain the above copyright
12
 *     notice, this list of conditions and the following disclaimer.
13
 *
14
 *   * Redistributions in binary form must reproduce the above copyright
15
 *     notice, this list of conditions and the following disclaimer in
16
 *     the documentation and/or other materials provided with the
17
 *     distribution.
18
 *
19
 *   * Neither the names of the copyright holders nor the names of his
20
 *     contributors may be used to endorse or promote products derived
21
 *     from this software without specific prior written permission.
22
 *
23
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34
 * POSSIBILITY OF SUCH DAMAGE.
35
 *
36
 * @category  Libraries
37
 * @package   Storyplayer/Modules/Browser
38
 * @author    Stuart Herbert <[email protected]>
39
 * @copyright 2011-present Mediasift Ltd www.datasift.com
40
 * @license   http://www.opensource.org/licenses/bsd-license.php  BSD License
41
 * @link      http://datasift.github.io/storyplayer
42
 */
43
44
namespace Storyplayer\SPv2\Modules\Browser;
45
46
use Prose\E5xx_ActionFailed;
47
use Prose\E5xx_UnknownDomElementType;
48
49
/**
50
 * Base class for all the *ElementAction helper classes
51
 *
52
 * The main thing this base class offers is the process for converting a
53
 * faked element type (such as 'buttonLabelled') into something specific
54
 * that we can go and find
55
 *
56
 * @category  Libraries
57
 * @package   Storyplayer/Browser
58
 * @author    Stuart Herbert <[email protected]>
59
 * @copyright 2011-present Mediasift Ltd www.datasift.com
60
 * @license   http://www.opensource.org/licenses/bsd-license.php  BSD License
61
 * @link      http://datasift.github.io/storyplayer
62
 */
63
class BaseElementAction
64
{
65
    use VisibleElementFinder;
66
67
    const SINGLE_TARGET = 1;
68
    const PLURAL_TARGET = 2;
69
70
    protected $countTypes = array(
71
        "any"       => "any",
72
        "several"   => "several",
73
        "no"        => 0,
74
        "zero"      => 0,
75
        "one"       => 1,
76
        "a"         => 1,
77
        "an"        => 2,
78
        "two"       => 2,
79
        "three"     => 3,
80
        "four"      => 4,
81
        "five"      => 5,
82
        "six"       => 6,
83
        "seven"     => 7,
84
        "eight"     => 8,
85
        "nine"      => 9,
86
        "ten"       => 10,
87
        "eleven"    => 11,
88
        "twelve"    => 12,
89
        "thirteen"  => 13,
90
        "fourteen"  => 14,
91
        "fifteen"   => 15,
92
        "sixteen"   => 16,
93
        "seventeen" => 17,
94
        "eighteen"  => 18,
95
        "nineteen"  => 19,
96
        "twenty"    => 20,
97
    );
98
99
    protected $indexTypes = array(
100
        "first"       => 0,
101
        "second"      => 1,
102
        "third"       => 2,
103
        "fourth"      => 3,
104
        "fifth"       => 4,
105
        "sixth"       => 5,
106
        "seventh"     => 6,
107
        "eighth"      => 7,
108
        "ninth"       => 8,
109
        "tenth"       => 9,
110
        "eleventh"    => 10,
111
        "twelfth"     => 11,
112
        "thirteenth"  => 12,
113
        "fourteenth"  => 13,
114
        "fifteenth"   => 14,
115
        "sixteenth"   => 15,
116
        "seventeenth" => 16,
117
        "eighteenth"  => 17,
118
        "nineteenth"  => 18,
119
        "twentieth"   => 19,
120
    );
121
122
    protected $tagTypes = array(
123
        'button'        => array('input', 'button'),
124
        'buttons'       => array('input','button'),
125
        'cell'          => 'td',
126
        'cells'         => 'td',
127
        'heading'       => array('h1', 'h2', 'h3', 'h4', 'h5','h6'),
128
        'headings'      => array('h1', 'h2', 'h3', 'h4', 'h5','h6'),
129
        'link'          => 'a',
130
        'links'         => 'a',
131
        'orderedlist'   => 'ol',
132
        'unorderedlist' => 'ul'
133
    );
134
135
    protected $targetTypes = array(
136
        'box'           => self::SINGLE_TARGET,
137
        'boxes'         => self::PLURAL_TARGET,
138
        'button'        => self::SINGLE_TARGET,
139
        'buttons'       => self::PLURAL_TARGET,
140
        'cell'          => self::SINGLE_TARGET,
141
        'cells'         => self::PLURAL_TARGET,
142
        'dropdown'      => self::SINGLE_TARGET,
143
        'dropdowns'     => self::PLURAL_TARGET,
144
        'element'       => self::SINGLE_TARGET,
145
        'elements'      => self::PLURAL_TARGET,
146
        'field'         => self::SINGLE_TARGET,
147
        'fields'        => self::PLURAL_TARGET,
148
        'heading'       => self::SINGLE_TARGET,
149
        'headings'      => self::PLURAL_TARGET,
150
        'link'          => self::SINGLE_TARGET,
151
        'links'         => self::PLURAL_TARGET,
152
        'orderedlist'   => self::SINGLE_TARGET,
153
        'span'          => self::SINGLE_TARGET,
154
        'unorderedlist' => self::SINGLE_TARGET
155
    );
156
157
    protected $searchTypes = array (
158
        'id'            => 'ById',
159
        'label'         => 'ByLabel',
160
        'labelled'      => 'ByLabel',
161
        'named'         => 'ByName',
162
        'name'          => 'ByName',
163
        'text'          => 'ByText',
164
        'class'         => 'ByClass',
165
        'placeholder'   => 'ByPlaceholder',
166
        'title'         => 'ByTitle',
167
        'labelidortext' => 'ByLabelIdText',
168
    );
169
170
    protected $baseElement;
171
172
    public function __construct($baseElement)
173
    {
174
        $this->baseElement = $baseElement;
175
    }
176
177
    /**
178
     * @param  string $methodName
179
     *         camelCase string to parse
180
     * @return array<string>
181
     *         $methodName broken into individual words, all lower-cased
182
     */
183
    protected function convertMethodNameToWords($methodName)
184
    {
185
        // turn the method name into an array of words
186
        $words = explode(' ', strtolower(preg_replace('/([^A-Z])([A-Z])/', "$1 $2", $methodName)));
187
188
        // all done
189
        return $words;
190
    }
191
192
    /**
193
     * @param  array<string> $words
194
     *         a list of words to examine
195
     * @return int|null
196
     */
197
    protected function determineCountType($words)
198
    {
199
        foreach ($words as $word) {
200
            if (isset($this->countTypes[$word])) {
201
                return $this->countTypes[$word];
202
            }
203
        }
204
205
        // if we do not recognise the word, tell the caller
206
        return null;
207
    }
208
209
    /**
210
     * @param  array<string> $words
211
     *         a list of words to examine
212
     * @return int|null
213
     */
214 View Code Duplication
    protected function determineIndexType($words)
215
    {
216
        foreach ($words as $word) {
217
            if (isset($this->indexTypes[$word])) {
218
                return $this->indexTypes[$word];
219
            }
220
        }
221
222
        // if we do not recognise the word, we want the first match
223
        return 0;
224
    }
225
226
    /**
227
     * @param  array<string> $words
228
     *         a list of words to examine
229
     * @return string|null
230
     */
231 View Code Duplication
    protected function determineSearchType($words)
232
    {
233
        foreach ($words as $word) {
234
            if (isset($this->searchTypes[$word])) {
235
                return $this->searchTypes[$word];
236
            }
237
        }
238
239
        // if we do not recognise the word, tell the caller
240
        return null;
241
    }
242
243
    /**
244
     * @param  array<string> $words
245
     *         a list of words to examine
246
     * @return string
247
     */
248
    protected function determineTargetType($words)
249
    {
250
        foreach ($words as $word) {
251
            if (isset($this->targetTypes[$word])) {
252
                return $word;
253
            }
254
        }
255
256
        // if we do not recognise the word, substitute a suitable default
257
        return 'field';
258
    }
259
260
    /**
261
     * @param  string $targetType
262
     * @return string
263
     */
264
    protected function determineTagType($targetType)
265
    {
266
        // do we have a specific tag to look for?
267
        if (isset($this->tagTypes[$targetType])) {
268
            return $this->tagTypes[$targetType];
269
        }
270
271
        // no, so return the default to feed into xpath
272
        return '*';
273
    }
274
275
    /**
276
     * @param  string $targetType
277
     * @return bool
278
     */
279
    protected function isPluralTarget($targetType)
280
    {
281
        // is this a valid target type?
282
        if (!isset($this->targetTypes[$targetType])) {
283
            throw new E5xx_UnknownDomElementType($targetType);
284
        }
285
286
        // is this a plural target?
287
        if ($this->targetTypes[$targetType] == self::PLURAL_TARGET) {
288
            return true;
289
        }
290
291
        // no, it is not
292
        return false;
293
    }
294
295
    protected function retrieveElement($methodName, $methodArgs)
296
    {
297
        // we need to know which element they want
298
        $words = $this->convertMethodNameToWords($methodName);
299
        $indexType  = $this->determineIndexType($words);
300
301
        // get all the elements that match
302
        $elements = $this->retrieveElements($methodName, $methodArgs);
303
304
        // reduce the list down to a single matching element
305
        $element = $this->returnNthVisibleElement($indexType, $elements);
306
307
        // all done
308
        return $element;
309
    }
310
311
    /**
312
     * @param  string $methodName
313
     * @param  array<mixed> $methodArgs
314
     * @return array
315
     */
316
    protected function retrieveElements($methodName, $methodArgs)
317
    {
318
        $words = $this->convertMethodNameToWords($methodName);
319
320
        $targetType = $this->determineTargetType($words);
321
322
        // what are we searching for?
323
        $searchTerm = $methodArgs[0];
324
325
        $searchType = $this->determineSearchType($words);
326
        if ($searchType === null) {             // we do not understand how to find the target field
327
            throw new E5xx_ActionFailed(__CLASS__ . '::' . $methodName, "could not work out how to find the target to action upon");
328
        }
329
330
        // what tag(s) do we want to narrow our search to?
331
        $tag = $this->determineTagType($targetType);
332
333
        // how are we searching for matching elements?
334
        $searchMethod = 'getElements' . $searchType;
335
336
        // let's go find our element
337
        $searchObject = new DomElementSearch($this->baseElement);
338
        $elements = $searchObject->$searchMethod($searchTerm, $tag);
339
340
        // all done
341
        return $elements;
342
    }
343
}
344