Completed
Push — master ( 6ab195...1e296c )
by Faiz
02:51
created

XMLRepository::initialize()   A

Complexity

Conditions 4
Paths 8

Size

Total Lines 28

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 4.1574

Importance

Changes 0
Metric Value
dl 0
loc 28
ccs 11
cts 14
cp 0.7856
rs 9.472
c 0
b 0
f 0
cc 4
nc 8
nop 0
crap 4.1574
1
<?php
2
3
namespace FaizShukri\Quran\Repositories\Source;
4
5
use FaizShukri\Quran\Exceptions\AyahInvalid;
6
use FaizShukri\Quran\Exceptions\SurahInvalid;
7
use FaizShukri\Quran\Exceptions\TranslationNotExists;
8
use FaizShukri\Quran\Supports\Config;
9
use FaizShukri\Quran\Supports\Downloader;
10
use FaizShukri\Quran\Supports\XML;
11
12
class XMLRepository implements SourceInterface
13
{
14
    private $config;
15
16 78
    public function setConfig(Config $config)
17
    {
18 78
        $this->config = $config;
19 78
    }
20
21 84
    public function surah($surah = null)
22
    {
23 84
        if (is_int($surah) && ($surah < 1 || $surah > 114)) {
24 3
            throw new SurahInvalid();
25
        }
26
27 81
        $xmlFile = $this->config->get('storage_path').'/quran-data.xml';
28 81
        $xml = new XML($xmlFile);
29
30 81
        $xpath = '//suras/sura';
31
32 81
        if ($surah != null) {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $surah of type null|integer against null; this is ambiguous if the integer can be zero. Consider using a strict comparison !== instead.
Loading history...
33 72
            $xpath .= "[@index={$surah}]";
34
        }
35
36 81
        $xpathResult = $xml->find($xpath);
37
38 81
        if ($surah != null) {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $surah of type null|integer against null; this is ambiguous if the integer can be zero. Consider using a strict comparison !== instead.
Loading history...
39 72
            $sura = (array) current($xpathResult);
40 72
            return $sura['@attributes'];
41
        }
42
43
        // If `$surah` is null, then get all chapters
44 18
        $result = [];
45
46 18
        foreach ($xpathResult as $node) {
47 18
            $node = (array) $node;
48 18
            $verse = $node['@attributes'];
49 18
            $result[$verse['index']] = (object) $verse;
50
        }
51
52 18
        return $result;
53
    }
54
55 66
    public function ayah($surah, $ayah, $translation = 'ar')
56
    {
57 66
        $xmlFile = $this->config->get('storage_path').'/'.$translation.'.xml';
58
59
        // If files not exist, get the first match
60 66
        if (!file_exists($xmlFile)) {
61 63
            $xmlFile = $this->firstMatchAvailableTranslation($translation);
62
        }
63
64 66
        if ($xmlFile === false) {
65 3
            throw new TranslationNotExists('Translation '.$translation." didn't exists. Please check your config.");
66
        }
67
68 63
        $xml = new XML($xmlFile);
69 63
        $result = [];
70
71 63
        $max_ayah = intval($this->surah(intval($surah))['ayas']);
72 60
        $xpath = '//sura[@index='.$surah.']/aya['.implode(' or ', array_map(function ($a) use ($max_ayah) {
73 60
                if ($a > $max_ayah) {
74 3
                    throw new AyahInvalid();
75
                }
76
77 57
                return '@index='.$a;
78 60
            }, $ayah)).']';
79
80 57
        $xpathResult = $xml->find($xpath);
81
82 57
        foreach ($xpathResult as $node) {
83 57
            $node = (array) $node;
84 57
            $verse = $node['@attributes'];
85 57
            $result[$verse['index']] = $verse['text'];
86
        }
87
88 57
        return $result;
89
    }
90
91 78
    public function initialize()
92
    {
93
        // If original quran not exist in storage_path, copy one
94 78
        $quran_source = realpath(__DIR__.'/../../../data/ar.quran.xml');
95 78
        $quran_dest = $this->config->get('storage_path').'/ar.quran.xml';
96
97 78
        $meta_source = realpath(__DIR__.'/../../../data/quran-data.xml');
98 78
        $meta_dest = $this->config->get('storage_path').'/quran-data.xml';
99
100
        // If storage path didn't exist, create it
101 78
        if (!file_exists($this->config->get('storage_path'))) {
102
            mkdir($this->config->get('storage_path'));
103
        }
104
105
        // Copy quran
106 78
        if (!file_exists($quran_dest)) {
107
            copy($quran_source, $quran_dest);
108
        }
109
110
        // Copy metadata
111 78
        if (!file_exists($meta_dest)) {
112
            copy($meta_source, $meta_dest);
113
        }
114
115
        // Sync translation files to storage path
116 78
        $dw = new Downloader($this->config);
117 78
        $dw->sync();
118 78
    }
119
120
    /**
121
     * Get the first match xml from translation.
122
     *
123
     * @param string $translation Translation prefix or short form
124
     *
125
     * @return string|false String of path to the translation if exists, or false otherwise
126
     */
127 63
    private function firstMatchAvailableTranslation($translation)
128
    {
129 63
        $dir = new \DirectoryIterator($this->config->get('storage_path'));
130
131 63
        foreach ($dir as $fileinfo) {
132 63
            if (!$fileinfo->isDot()) {
133 63
                $filename = $fileinfo->getFilename();
134
135
                // If match the first file with translation prefix, return it
136 63
                $yes = preg_match('/^'.$translation.'/', $filename);
137 63
                if ($yes === 1) {
138 61
                    return $this->config->get('storage_path').'/'.$filename;
139
                }
140
            }
141
        }
142
143 3
        return false;
144
    }
145
146
147
    public function translations()
148
    {
149
        $dir = scandir($this->config->get('storage_path'));
150
        $translations = array_filter($dir, function($a){
151
            return ($a !== "." && $a !== ".." && $a !== 'quran-data.xml');
152
        });
153
154
        return array_values(
155
            array_map(function($a){ return str_replace(".xml", "", $a); }, $translations)
156
        );
157
    }
158
159
    public function addTranslation($translation)
160
    {
161
        // TODO: Implement addTranslation() method.
162
    }
163
}
164