XMLRepository::firstMatchAvailableTranslation()   A
last analyzed

Complexity

Conditions 4
Paths 4

Size

Total Lines 17
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 4

Importance

Changes 2
Bugs 0 Features 1
Metric Value
cc 4
eloc 8
nc 4
nop 1
dl 0
loc 17
ccs 9
cts 9
cp 1
crap 4
rs 10
c 2
b 0
f 1
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 60
    public function setConfig(Config $config)
17
    {
18 60
        $this->config = $config;
19 30
    }
20
21 64
    public function surah($surah = null)
22
    {
23 64
        if (is_int($surah) && ($surah < 1 || $surah > 114)) {
24 2
            throw new SurahInvalid();
25
        }
26
27 62
        $xmlFile = $this->config->get('storage_path').'/quran-data.xml';
28 62
        $xml = new XML($xmlFile);
29
30 62
        $xpath = '//suras/sura';
31
32 62
        if ($surah != null) {
33 56
            $xpath .= "[@index={$surah}]";
34
        }
35
36 62
        $xpathResult = $xml->find($xpath);
37
38 62
        if ($surah != null) {
39 56
            $sura = (array) current($xpathResult);
40 56
            return $sura['@attributes'];
41
        }
42
43
        // If `$surah` is null, then get all chapters
44 12
        $result = [];
45
46 12
        foreach ($xpathResult as $node) {
47 12
            $node = (array) $node;
48 12
            $verse = $node['@attributes'];
49 12
            $result[$verse['index']] = (object) $verse;
50
        }
51
52 12
        return $result;
53
    }
54
55 52
    public function ayah($surah, $ayah, $translation = 'ar')
56
    {
57 52
        $xmlFile = $this->config->get('storage_path').'/'.$translation.'.xml';
58
59
        // If files not exist, get the first match
60 52
        if (!file_exists($xmlFile)) {
61 50
            $xmlFile = $this->firstMatchAvailableTranslation($translation);
62
        }
63
64 52
        if ($xmlFile === false) {
65 2
            throw new TranslationNotExists('Translation \''.$translation."' didn't exists. Add it to config first before use.");
66
        }
67
68 50
        $xml = new XML($xmlFile);
69 50
        $result = [];
70
71 50
        $max_ayah = intval($this->surah(intval($surah))['ayas']);
72 48
        $xpath = '//sura[@index='.$surah.']/aya['.implode(' or ', array_map(function ($a) use ($max_ayah) {
73 48
                if ($a > $max_ayah) {
74 2
                    throw new AyahInvalid();
75
                }
76
77 46
                return '@index='.$a;
78 48
            }, $ayah)).']';
79
80 46
        $xpathResult = $xml->find($xpath);
81
82 46
        foreach ($xpathResult as $node) {
83 46
            $node = (array) $node;
84 46
            $verse = $node['@attributes'];
85 46
            $result[$verse['index']] = $verse['text'];
86
        }
87
88 46
        return $result;
89
    }
90
91 60
    public function initialize()
92
    {
93
        // If original quran not exist in storage_path, copy one
94 60
        $quran_source = realpath(__DIR__.'/../../../data/ar.quran.xml');
95 60
        $quran_dest = $this->config->get('storage_path').'/ar.quran.xml';
96
97 60
        $meta_source = realpath(__DIR__.'/../../../data/quran-data.xml');
98 60
        $meta_dest = $this->config->get('storage_path').'/quran-data.xml';
99
100
        // If storage path didn't exist, create it
101 60
        if (!file_exists($this->config->get('storage_path'))) {
102
            mkdir($this->config->get('storage_path'));
103
        }
104
105
        // Copy quran
106 60
        if (!file_exists($quran_dest)) {
107
            copy($quran_source, $quran_dest);
108
        }
109
110
        // Copy metadata
111 60
        if (!file_exists($meta_dest)) {
112
            copy($meta_source, $meta_dest);
113
        }
114
115
        // Sync translation files to storage path
116 60
        $dw = new Downloader($this->config);
117 60
        $dw->sync();
118 30
    }
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 50
    private function firstMatchAvailableTranslation($translation)
128
    {
129 50
        $dir = new \DirectoryIterator($this->config->get('storage_path'));
130
131 50
        foreach ($dir as $fileinfo) {
132 50
            if (!$fileinfo->isDot()) {
133 50
                $filename = $fileinfo->getFilename();
134
135
                // If match the first file with translation prefix, return it
136 50
                $yes = preg_match('/^'.$translation.'/', $filename);
137 50
                if ($yes === 1) {
138 49
                    return $this->config->get('storage_path').'/'.$filename;
139
                }
140
            }
141
        }
142
143 2
        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