Completed
Push — master ( adeed7...b5464f )
by Akpé Aurelle Emmanuel Moïse
02:31
created

similar_text::is_ascii()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 3
dl 0
loc 7
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 1
1
<?php
2
/**
3
*
4
* @Name : similar-text
5
* @Programmer : Akpé Aurelle Emmanuel Moïse Zinsou
6
* @Date : 2019-04-01
7
* @Released under : https://github.com/manuwhat/similar-text/blob/master/LICENSE
8
* @Repository : https://github.com/manuwhat/similar
9
*
10
**/
11
namespace{
12
    function SimilarText(
13
        $firstString,
14
        $secondString,
15
        $round=2,
16
        $insensitive=true,
17
        &$stats=false,
18
        $getParts=false
19
                        ) {
20
        return EZAMA\similar_text::similarText(
21
            $firstString,
22
            $secondString,
23
            $round,
24
            $insensitive,
25
            $stats,
26
            $getParts
27
                                        );
28
    }
29
    
30
    function areAnagrams($a, $b)
31
    {
32
        return EZAMA\similar_text::areAnagrams($a, $b);
33
    }
34
    
35
    function similarButNotEqual($a, $b)
36
    {
37
        return   EZAMA\similar_text::similarButNotEqual($a, $b);
38
    }
39
}
40
41
namespace EZAMA{
42
        
43
    class similar_text
44
    {
45
        private function __construct()
46
        {
47
        }
48
        public static function similarText($a, $b, $round=2, $insensitive=true, &$stats=false, $getParts=false)
49
        {
50
            if (!is_string($a)||!is_string($b)) {
51
                return false;
52
            }
53
            if ($insensitive) {
54
                $a=self::strtolower($a);
55
                $b=self::strtolower($b);
56
            }
57
            /* prevent bad types and useless memory usage due to for example array instead of simple boolean */
58
            unset($insensitive);
59
            $getParts=(bool)$getParts;
60
            /*  ******************************************************************************************** */
61
            $a=self::split($a);
62
            $b=self::split($b);
63
            $ca=count($a);
0 ignored issues
show
Bug introduced by
It seems like $a can also be of type false; however, parameter $var of count() does only seem to accept Countable|array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

63
            $ca=count(/** @scrutinizer ignore-type */ $a);
Loading history...
64
            $cb=count($b);
65
            if ($ca<$cb) {
66
                $stats=self::getStats($cb, $a, self::_check($a, $b, $getParts, $round), $getParts, $round);
67
            } else {
68
                $stats=self::getStats($ca, $b, self::_check($b, $a, $getParts, $round), $getParts, $round);
69
            }
70
            return $stats['similar'];
71
        }
72
        
73
        protected static function _check($a, $b, $getParts, $round)
74
        {
75
            if ($getParts) {
76
                $diff[]=array_diff($a, $b);
0 ignored issues
show
Comprehensibility Best Practice introduced by
$diff was never initialized. Although not strictly required by PHP, it is generally a good practice to add $diff = array(); before regardless.
Loading history...
77
                $diff[]=array_diff($b, $a);
78
            }
79
            $diff[]=array_intersect($a, $b);
80
            $diff[]=round(count(array_intersect(self::getParts($a, $c), self::getParts($b)))/$c*100, $round);
81
            $diff[]=$a===$b;
82
            return $diff;
83
        }
84
        
85
        protected static function getStats($ca, $b, $diff, $getParts, $round)
86
        {
87
            if ($getParts) {
88
                $stats['similar']=round(count($diff[2])*100/$ca, $round);
0 ignored issues
show
Comprehensibility Best Practice introduced by
$stats was never initialized. Although not strictly required by PHP, it is generally a good practice to add $stats = array(); before regardless.
Loading history...
89
                $stats['substr']=$diff[3];
90
                $stats['contain']=($diff[2]===$b)?true:false;
91
                $stats['equal']=$diff[4];
92
                $stats['a-b']=$diff[0];
93
                $stats['b-a']=$diff[1];
94
                $stats['a&b']=$diff[2];
95
            } else {
96
                $stats['similar']=round(count($diff[0])*100/$ca, $round);
97
                $stats['substr']=$diff[1];
98
                $stats['contain']=($diff[0]===$b)?true:false;
99
                $stats['equal']=$diff[2];
100
            }
101
            return $stats;
102
        }
103
104
        protected static function getParts($b, &$c=0)
105
        {
106
            $tmp='';
107
            $c=0;
108
            foreach ($b as $k=>$v) {
109
                $tmp.=$v;
110
                if (ctype_space($v)) {
111
                    $parts[]=$tmp;
112
                    $parts[]=$v;
113
                    $c+=2;
114
                    $tmp='';
115
                }
116
            }
117
            if (!empty($tmp)) {
118
                $parts[]=$tmp;
119
                $c++;
120
            }
121
            return $parts;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $parts does not seem to be defined for all execution paths leading up to this point.
Loading history...
122
        }
123
        
124
        
125
        
126
        protected static function is_ascii($str)
127
        {
128
            if ('' === $str) {
129
                return true;
130
            }
131
132
            return !preg_match('/[^\x09\x10\x13\x0A\x0D\x20-\x7E]/', $str);
133
        }
134
        
135
        protected static function strtolower($str)
136
        {
137
            return join(
0 ignored issues
show
Bug introduced by
The call to join() has too few arguments starting with pieces. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

137
            return /** @scrutinizer ignore-call */ join(

This check compares calls to functions or methods with their respective definitions. If the call has less arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
138
                array_map(
0 ignored issues
show
Bug introduced by
array_map(function(...) .../ }, self::split($str)) of type array is incompatible with the type string expected by parameter $glue of join(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

138
                /** @scrutinizer ignore-type */ array_map(
Loading history...
139
                    function ($val) {
140
                        if (self::is_ascii($val)) {
141
                            return strtolower($val);
142
                        }
143
                        return $val;
144
                    },
145
                    self::split($str)
0 ignored issues
show
Bug introduced by
It seems like self::split($str) can also be of type false; however, parameter $arr1 of array_map() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

145
                    /** @scrutinizer ignore-type */ self::split($str)
Loading history...
146
            )
147
                        )
148
                       ;
149
        }
150
        
151
        protected static function split($str)
152
        {
153
            if (!is_string($str)) {
154
                return false;
155
            }
156
            static $split=[];
157
            static $old='';
158
            if ($old===$str) {
159
                return $split;
160
            } else {
161
                $old=$str;
162
                $split=preg_split('//u', $str, -1, PREG_SPLIT_NO_EMPTY);
163
                return $split;
164
            }
165
        }
166
        
167
        public static function areAnagrams($a, $b)
168
        {
169
            return  self::similarText($a, $b, 2, true, $check)?$check['similar'] === 100.0&&$check['contain']===true:false;
170
        }
171
        
172
        public static function similarButNotEqual($a, $b)
173
        {
174
            return   self::similarText($a, $b, 2, true, $check)&&is_array($check)&&$check['equal']===true?false:true;
175
        }
176
    }
177
}
178