Completed
Pull Request — master (#25)
by ilyes
04:01
created

Integer::__construct()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2.0185

Importance

Changes 0
Metric Value
dl 0
loc 11
ccs 5
cts 6
cp 0.8333
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 5
nc 2
nop 1
crap 2.0185
1
<?php
2
3
/**
4
 * \AppserverIo\Lang\Integer
5
 *
6
 * NOTICE OF LICENSE
7
 *
8
 * This source file is subject to the Open Software License (OSL 3.0)
9
 * that is available through the world-wide-web at this URL:
10
 * http://opensource.org/licenses/osl-3.0.php
11
 *
12
 * PHP version 5
13
 *
14
 * @author    Tim Wagner <[email protected]>
15
 * @copyright 2015 TechDivision GmbH <[email protected]>
16
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
17
 * @link      https://github.com/appserver-io/lang
18
 * @link      http://www.appserver.io
19
 */
20
21
namespace AppserverIo\Lang;
22
23
/**
24
 * This class implements functionality to handle
25
 * a integer value as object.
26
 *
27
 * @author    Tim Wagner <[email protected]>
28
 * @copyright 2015 TechDivision GmbH <[email protected]>
29
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
30
 * @link      https://github.com/appserver-io/lang
31
 * @link      http://www.appserver.io
32
 */
33
class Integer extends Number implements \Serializable
34
{
35
36
    /**
37
     * The value of the Integer.
38
     *
39
     * @var integer
40
     */
41
    protected $value;
42
43
    /**
44
     * Constructs a newly allocated <code>Integer</code> object that
45
     * represents the primitive <code>integer</code> argument.
46
     *
47
     * @param integer $value The value to be represented by the <code>Integer</code>.
48
     *
49
     * @throws \AppserverIo\Lang\NumberFormatException Is thrown if the passed value is not an integer
50
     */
51 17
    public function __construct($value)
52
    {
53
        // initialize property default values here, as declarative default values may break thread safety,
54
        // when utilizing static and non-static access on class methods within same thread context!
55 17
        $this->value = null;
56
57 17
        if (!is_int($value)) {
58
            NumberFormatException::forInputString($value);
59
        }
60 17
        $this->value = $value;
61 17
    }
62
63
    /**
64
     * This method returns the class name as
65
     * a string.
66
     *
67
     * @return string
68
     */
69 1
    public static function __getClass()
70
    {
71 1
        return __CLASS__;
72
    }
73
74
    /**
75
     * Returns a <code>Integer</code> object holding the
76
     * <code>float</code> value represented by the argument string
77
     * <code>s</code>.
78
     * <p>
79
     * If <code>s</code> is <code>null</code>, then a
80
     * <code>NullPointerException</code> is thrown.
81
     * <p>
82
     * Leading and trailing whitespace characters in <code>s</code>
83
     * are ignored. The rest of <code>s</code> should constitute a
84
     * <i>Integer</i> as described by the lexical syntax rules:
85
     * <blockquote><i>
86
     * <dl>
87
     * <dt>Integer:
88
     * <dd><i>Sign<sub>opt</sub></i> <code>NaN</code>
89
     * <dd><i>Sign<sub>opt</sub></i> <code>Infinity</code>
90
     * <dd>Sign<sub>opt</sub> FloatingPointLiteral
91
     * </dl>
92
     * </i></blockquote>
93
     * where <i>Sign</i> and <i>FloatingPointLiteral</i> are as
94
     * defined in <a href="http://java.sun.com/docs/books/jls/second_edition/
95
     * html/lexical.doc.html#230798">&sect;3.10.2</a>
96
     * of the <a href="http://java.sun.com/docs/books/jls/html/">Java
97
     * Language Specification</a>. If <code>s</code> does not have the
98
     * form of a <i>Integer</i>, then a
99
     * <code>NumberFormatException</code> is thrown. Otherwise,
100
     * <code>s</code> is regarded as representing an exact decimal
101
     * value in the usual "computerized scientific notation"; this
102
     * exact decimal value is then conceptually converted to an
103
     * "infinitely precise" binary value that is then rounded to type
104
     * <code>float</code> by the usual round-to-nearest rule of IEEE
105
     * 754 floating-point arithmetic, which includes preserving the
106
     * sign of a zero value. Finally, a <code>Float</code> object
107
     * representing this <code>float</code> value is returned.
108
     * <p>
109
     * To interpret localized string representations of a
110
     * floating-point value, use subclasses of {@link
111
     * java.text.NumberFormat}.
112
     *
113
     * <p>Note that trailing format specifiers, specifiers that
114
     * determine the type of a floating-point literal
115
     * (<code>1.0f</code> is a <code>float</code> value;
116
     * <code>1.0d</code> is a <code>double</code> value), do
117
     * <em>not</em> influence the results of this method. In other
118
     * words, the numerical value of the input string is converted
119
     * directly to the target floating-point type. In general, the
120
     * two-step sequence of conversions, string to <code>double</code>
121
     * followed by <code>double</code> to <code>float</code>, is
122
     * <em>not</em> equivalent to converting a string directly to
123
     * <code>float</code>. For example, if first converted to an
124
     * intermediate <code>double</code> and then to
125
     * <code>float</code>, the string<br>
126
     * <code>"1.00000017881393421514957253748434595763683319091796875001d"
127
     * </code><br> results in the <code>float</code> value
128
     * <code>1.0000002f</code>; if the string is converted directly to
129
     * <code>float</code>, <code>1.000000<b>1</b>f</code> results.
130
     *
131
     * @param \AppserverIo\Lang\Strng $string The string to be parsed
132
     *
133
     * @return \AppserverIo\Lang\Integer A <code>Integer</code> object holding the value represented by the <code>Strng</code> argument
134
     * @exception \AppserverIo\Lang\NumberFormatException If the string does not contain a parsable number
135
     */
136 4 View Code Duplication
    public static function valueOf(Strng $string)
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...
137
    {
138 4
        if (! preg_match("/([0-9-]+)/", $string->stringValue())) {
139
            NumberFormatException::forInputString($string->stringValue());
0 ignored issues
show
Documentation introduced by
$string->stringValue() is of type array, 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...
140
        }
141 4
        if (! is_numeric($string->stringValue())) {
142 2
            NumberFormatException::forInputString($string->stringValue());
0 ignored issues
show
Documentation introduced by
$string->stringValue() is of type array, 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...
143
        }
144 2
        return new Integer((integer) $string->stringValue());
145
    }
146
147
    /**
148
     * Returns a new <code>Integer</code> initialized to the value
149
     * represented by the specified <code>Strng</code>, as performed
150
     * by the <code>valueOf</code> method of class <code>Integer</code>.
151
     *
152
     * @param Strng $string The string to be parsed.
153
     *
154
     * @return \AppserverIo\Lang\Integer The <code>Integer</code> value represented by the string argument.
155
     * @exception \AppserverIo\Lang\NumberFormatException If the string does not contain a parsable <code>Integer</code>.
156
     * @see \AppserverIo\Lang\Integer::valueOf($string)
157
     */
158 2
    public static function parseInteger(Strng $string)
159
    {
160 2
        return Integer::valueOf($string)->intValue();
161
    }
162
163
    /**
164
     * Returns the value of the specified number as a <code>float</code>.
165
     * This may involve rounding.
166
     *
167
     * @return float The numeric value represented by this object after conversion to type <code>float</code>
168
     * @see \AppserverIo\Lang\Number::floatValue()
169
     */
170 1
    public function floatValue()
171
    {
172 1
        return (float) $this->value;
173
    }
174
175
    /**
176
     * Returns the value of the specified number as an <code>int</code>.
177
     * This may involve rounding or truncation.
178
     *
179
     * @return integer The numeric value represented by this object after conversion to type <code>int</code>
180
     * @see \AppserverIo\Lang\Number::intValue()
181
     */
182 14
    public function intValue()
183
    {
184 14
        return $this->value;
185
    }
186
187
    /**
188
     * Returns the value of the specified number as a <code>double</code>.
189
     * This may involve rounding.
190
     *
191
     * @return double The numeric value represented by this object after conversion to type <code>double</code>
192
     * @see \AppserverIo\Lang\Number::doubleValue()
193
     */
194 1
    public function doubleValue()
195
    {
196 1
        return (double) $this->value;
197
    }
198
199
    /**
200
     * This method has to be called to serialize the Integer.
201
     *
202
     * @return string Returns a serialized version of the Integer
203
     * @see \Serializable::serialize()
204
     */
205 1
    public function serialize()
206
    {
207 1
        return serialize($this->value);
208
    }
209
210
    /**
211
     * This method unserializes the passed string and initializes the Integer
212
     * itself with the data.
213
     *
214
     * @param string $data Holds the data of the instance as serialized string
215
     *
216
     * @return void
217
     * @see \Serializable::unserialize($data)
218
     */
219 1
    public function unserialize($data)
220
    {
221 1
        $this->value = unserialize($data);
222 1
    }
223
224
    /**
225
     * This object as String returned.
226
     *
227
     * @return \AppserverIo\Lang\Strng The value as String.
228
     */
229
    public function toString()
230
    {
231
        return new Strng($this->value);
232
    }
233
234
    /**
235
     * This method returns the class as
236
     * a string representation.
237
     *
238
     * @return string The objects string representation
239
     * @see \AppserverIo\Lang\Object::__toString()
240
     */
241
    public function __toString()
242
    {
243
        $string = new Strng($this->value);
244
        return $string->stringValue();
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $string->stringValue(); (array) is incompatible with the return type of the parent method AppserverIo\Lang\Object::__toString of type string.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

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

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
245
    }
246
247
    /**
248
     * Returns true if the passed value is equal.
249
     *
250
     * @param \AppserverIo\Lang\Object $val The value to check
251
     *
252
     * @return boolean
253
     */
254 2
    public function equals(Object $val)
255
    {
256 2
        if ($val instanceof Integer) {
257 2
            return $this->intValue() == $val->intValue();
258
        }
259
        return false;
260
    }
261
262
    /**
263
     * Adds the value of the passed Integer.
264
     *
265
     * @param \AppserverIo\Lang\Integer $toAdd The Integer to add
266
     *
267
     * @return \AppserverIo\Lang\Integer The instance
268
     */
269 1
    public function add(Integer $toAdd)
270
    {
271 1
        $this->value += $toAdd->intValue();
272 1
        return $this;
273
    }
274
275
    /**
276
     * Subtracts the value of the passed Integer.
277
     *
278
     * @param \AppserverIo\Lang\Integer $toSubtract The integer to subtract
279
     *
280
     * @return \AppserverIo\Lang\Integer The instance
281
     */
282 1
    public function subtract(Integer $toSubtract)
283
    {
284 1
        $this->value -= $toSubtract->intValue();
285 1
        return $this;
286
    }
287
288
    /**
289
     * Multiplies the Integer with the passed one.
290
     *
291
     * @param \AppserverIo\Lang\Integer $toMultiply The Integer to multiply
292
     *
293
     * @return \AppserverIo\Lang\Integer The instance
294
     */
295 1
    public function multiply(Integer $toMultiply)
296
    {
297 1
        $this->value *= $toMultiply->intValue();
298 1
        return $this;
299
    }
300
301
    /**
302
     * Divides the Integer by the passed one.
303
     * As this is an Integer
304
     * the result will ALWAYS be casted to an Integer agains, what
305
     * means that everything after the decimal point will be cutted
306
     * of!
307
     *
308
     * @param \AppserverIo\Lang\Integer $dividyBy The Integer to dividy by
309
     *
310
     * @return \AppserverIo\Lang\Integer The instance
311
     */
312 2
    public function divide(Integer $dividyBy)
313
    {
314 2
        $this->value = intval(($this->value / $dividyBy->intValue()));
315 2
        return $this;
316
    }
317
318
    /**
319
     * The methods returns the remainder of division of objects value
320
     * by the passed divisor.
321
     *
322
     * @param \AppserverIo\Lang\Integer $divisor The divisor for the modulo operation
323
     *
324
     * @return \AppserverIo\Lang\Integer The remainder of the modulo operation
325
     */
326 1
    public function modulo(Integer $divisor)
327
    {
328 1
        return new Integer($this->value % $divisor->intValue());
329
    }
330
331
    /**
332
     * Returns TRUE if the object's value is greater than the passed one.
333
     *
334
     * @param \AppserverIo\Lang\Integer $val The value to test the object's value against
335
     *
336
     * @return boolean TRUE if the object's value is greater
337
     */
338 1
    public function greaterThan(Integer $val)
339
    {
340 1
        return $this->value > $val->intValue();
341
    }
342
343
    /**
344
     * Returns TRUE if the object's value is greater or equal than
345
     * the passed one.
346
     *
347
     * @param \AppserverIo\Lang\Integer $val The value to test the object's value against
348
     *
349
     * @return boolean TRUE if the object's value is greater or equal
350
     */
351 1
    public function greaterThanOrEqual(Integer $val)
352
    {
353 1
        return $this->value >= $val->intValue();
354
    }
355
356
    /**
357
     * Returns TRUE if the objects value is lower than the passed one.
358
     *
359
     * @param \AppserverIo\Lang\Integer $val The value to test the object's value against
360
     *
361
     * @return boolean TRUE if the objects value is lower
362
     */
363 1
    public function lowerThan(Integer $val)
364
    {
365 1
        return $this->value < $val->intValue();
366
    }
367
368
    /**
369
     * Returns TRUE if the objects value is lower or equal than
370
     * the passed one.
371
     *
372
     * @param \AppserverIo\Lang\Integer $val The value to test the objects value against
373
     *
374
     * @return boolean TRUE if the objects value is lower or equal
375
     */
376 1
    public function lowerThanOrEqual(Integer $val)
377
    {
378 1
        return $this->value <= $val->intValue();
379
    }
380
}
381