Completed
Push — 5.x ( e60e0a...9fe877 )
by Lars
05:10
created

Swift_CharacterStream_MbCharacterStream   A

Complexity

Total Complexity 13

Size/Duplication

Total Lines 122
Duplicated Lines 7.38 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 95%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 9
loc 122
ccs 38
cts 40
cp 0.95
rs 10
wmc 13
lcom 1
cbo 2

9 Methods

Rating   Name   Duplication   Size   Complexity  
A flushContents() 0 5 1
A importByteStream() 9 9 2
A importString() 0 5 1
A readBytes() 0 10 2
A setCharacterReaderFactory() 0 4 1
A read() 0 14 2
A setCharacterSet() 0 6 2
A write() 0 5 1
A setPointer() 0 4 1

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
use voku\helper\UTF8;
4
5
/**
6
 * A CharacterStream implementation which skips over all the manual processing
7
 *  performed by NgCharacterStream.
8
 *
9
 * @package Swift
10
 * @author  mappu
11
 */
12
class Swift_CharacterStream_MbCharacterStream implements Swift_CharacterStream
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...
13
{
14
15
    /**
16
     * @var string
17
     */
18
    private $_charset = 'utf-8';
19
20
    /**
21
     * @var int
22
     */
23
    private $_strpos = 0;
24
25
    /**
26
     * @var string
27
     */
28
    private $_buffer = '';
29
30
    /**
31
     * @var int
32
     */
33
    private $_strlen = 0;
34
35 62
    public function flushContents()
36
    {
37 62
        $this->_strpos = 0;
38 62
        $this->_buffer = '';
39 62
    }
40
41
    /**
42
     * @param Swift_OutputByteStream $os
43
     */
44 4 View Code Duplication
    public function importByteStream(\Swift_OutputByteStream $os)
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...
45
    {
46 4
        $this->flushContents();
47 4
        $blocks = 512;
48 4
        $os->setReadPointer(0);
49 4
        while (($read = $os->read($blocks)) !== false) {
50 4
            $this->write($read);
0 ignored issues
show
Bug introduced by
It seems like $read defined by $os->read($blocks) on line 49 can also be of type boolean; however, Swift_CharacterStream_MbCharacterStream::write() does only seem to accept string, 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...
51
        }
52 4
    }
53
54
    /**
55
     * @param string $string
56
     */
57 58
    public function importString($string)
58
    {
59 58
        $this->flushContents();
60 58
        $this->write($string);
61 58
    }
62
63
    /**
64
     * @param int $length
65
     *
66
     * @return false|string
67
     */
68 59
    public function read($length)
69
    {
70 59
        if ($this->_strpos >= $this->_strlen) {
71 56
            return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type declared by the interface Swift_CharacterStream::read 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...
72
        }
73
74 59
        $readChars = min($length, $this->_strlen - $this->_strpos);
75
76 59
        $ret = UTF8::substr($this->_buffer, $this->_strpos, $readChars, $this->_charset);
77
78 59
        $this->_strpos += $readChars;
79
80 59
        return $ret;
81
    }
82
83
    /**
84
     * @param int $length
85
     *
86
     * @return int[]|bool
87
     */
88 53
    public function readBytes($length)
89
    {
90 53
        $read = $this->read($length);
91
92 53
        if ($read !== false) {
93 53
            return array_map('ord', str_split($read, 1));
94
        } else {
95 53
            return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type declared by the interface Swift_CharacterStream::readBytes of type integer[].

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...
96
        }
97
    }
98
99
    /**
100
     * @param Swift_CharacterReaderFactory $factory
101
     */
102
    public function setCharacterReaderFactory(\Swift_CharacterReaderFactory $factory)
103
    {
104
        // Ignore
105
    }
106
107
    /**
108
     * @param string $charset
109
     */
110 126
    public function setCharacterSet($charset)
111
    {
112 126
        if ($charset) {
113 126
            $this->_charset = $charset;
114
        }
115 126
    }
116
117
    /**
118
     * @param int $charOffset
119
     */
120 1
    public function setPointer($charOffset)
121
    {
122 1
        $this->_strpos = $charOffset;
123 1
    }
124
125
    /**
126
     * @param string $chars
127
     */
128 62
    public function write($chars)
129
    {
130 62
        $this->_buffer .= $chars;
131 62
        $this->_strlen += UTF8::strlen($chars, $this->_charset);
132 62
    }
133
}
134