Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
24 / 24
100.00% covered (success)
100.00%
8 / 8
CRAP
100.00% covered (success)
100.00%
1 / 1
Equivset
100.00% covered (success)
100.00%
24 / 24
100.00% covered (success)
100.00%
8 / 8
14
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 all
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 normalize
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 isEqual
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 has
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 get
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 getIterator
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 load
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
4
1<?php
2/**
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 * http://www.gnu.org/copyleft/gpl.html
17 */
18
19namespace Wikimedia\Equivset;
20
21use ArrayIterator;
22use IteratorAggregate;
23use LogicException;
24use Wikimedia\Equivset\Exception\EquivsetException;
25
26/**
27 * Default Equivset
28 */
29class Equivset implements EquivsetInterface, IteratorAggregate {
30
31    /**
32     * @var array<string,string>
33     */
34    protected array $data;
35
36    /**
37     * @var string
38     */
39    protected string $serializedPath;
40
41    /**
42     * Equivset
43     *
44     * @param array<string,string> $data Equivalent Set
45     * @param string $serializedPath Path of the serialized equivset array.
46     */
47    public function __construct( array $data = [], string $serializedPath = '' ) {
48        $this->data = $data;
49        $this->serializedPath = $serializedPath ?: __DIR__ . '/../dist/equivset.ser';
50    }
51
52    /**
53     * Get the equivset.
54     *
55     * @return array<string,string> An associative array of equivalent characters.
56     */
57    public function all(): array {
58        if ( !$this->data ) {
59            $this->data = $this->load();
60        }
61
62        return $this->data;
63    }
64
65    /**
66     * {@inheritdoc}
67     *
68     * @param string $value The string to normalize against the equivset.
69     * @return string
70     */
71    public function normalize( string $value ): string {
72        $data = $this->all();
73
74        return strtr( $value, $data );
75    }
76
77    /**
78     * {@inheritdoc}
79     *
80     * @param string $str1 The first string.
81     * @param string $str2 The second string.
82     *
83     * @return bool
84     */
85    public function isEqual( string $str1, string $str2 ): bool {
86        return $this->normalize( $str1 ) === $this->normalize( $str2 );
87    }
88
89    /**
90     * {@inheritdoc}
91     *
92     * @param string $key The character that was used.
93     * @return bool If the character has an equivalent.
94     */
95    public function has( string $key ): bool {
96        $data = $this->all();
97
98        return array_key_exists( $key, $data );
99    }
100
101    /**
102     * {@inheritdoc}
103     *
104     * @param string $key The character that was used.
105     * @return string The equivalent character.
106     * @throws LogicException If character does not exist.
107     */
108    public function get( string $key ): string {
109        $data = $this->all();
110
111        if ( !array_key_exists( $key, $data ) ) {
112            throw new LogicException( 'Equivalent Character Not Found' );
113        }
114
115        return $data[$key];
116    }
117
118    /**
119     * {@inheritdoc}
120     *
121     * @return ArrayIterator The complete Equivset.
122     */
123    public function getIterator(): ArrayIterator {
124        return new ArrayIterator( $this->all() );
125    }
126
127    /**
128     * Get the equivset.
129     *
130     * @return array<string,string> An associative array of equivalent characters.
131     * @throws \Throwable If the serialized equivset file is unreadable.
132     */
133    protected function load(): array {
134        if ( pathinfo( $this->serializedPath, PATHINFO_EXTENSION ) === 'php' ) {
135            // This will naturally throw if the file does not exist, is not readable,
136            // or can't be parsed.
137            return require $this->serializedPath;
138        }
139
140        // file_get_contents() will not fail at this point since none of the
141        // conditions that can cause a failure can happen at this point.
142        // See http://php.net/manual/en/function.file-get-contents.php
143
144        // phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
145        $contents = @file_get_contents( $this->serializedPath );
146        if ( $contents === false ) {
147            throw new EquivsetException( 'Serialized equivset file is unreadable' );
148        }
149
150        $data = unserialize( $contents );
151        if ( $data === false ) {
152            throw new EquivsetException( 'Unserializing serialized equivset failed' );
153        }
154
155        return $data;
156    }
157}