GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Pull Request — master (#7)
by
unknown
01:08
created

SitemapFactory::createSitemap()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 21
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 13
nc 6
nop 1
dl 0
loc 21
rs 9.0534
c 0
b 0
f 0
1
<?php
2
3
namespace Tackk\Cartographer;
4
5
use ArrayObject;
6
use DateTime;
7
use Iterator;
8
use League\Flysystem\FilesystemInterface;
9
use RuntimeException;
10
11
class SitemapFactory
12
{
13
    /**
14
     * @var FilesystemInterface
15
     */
16
    protected $filesystem = null;
17
18
    /**
19
     * @var string
20
     */
21
    protected $baseUrl = '';
22
23
    /**
24
     * @var array
25
     */
26
    protected $filesCreated = [];
27
28
    /**
29
     * @param FilesystemInterface $filesystem
30
     */
31
    public function __construct(FilesystemInterface $filesystem)
32
    {
33
        $this->filesystem = $filesystem;
34
    }
35
36
    /**
37
     * Gets the Filesystem.
38
     * @return FilesystemInterface
39
     */
40
    public function getFilesystem()
41
    {
42
        return $this->filesystem;
43
    }
44
45
    /**
46
     * Sets the Base URL for sitemap files.
47
     *
48
     * @param  string $baseUrl
49
     * @return $this
50
     */
51
    public function setBaseUrl($baseUrl)
52
    {
53
        $this->baseUrl = rtrim($baseUrl, '/');
54
55
        return $this;
56
    }
57
58
    /**
59
     * Gets the Base URL for sitemap files.
60
     * @return string
61
     */
62
    public function getBaseUrl()
63
    {
64
        return $this->baseUrl;
65
    }
66
67
    /**
68
     * Gets the array of files created.
69
     * @return array
70
     */
71
    public function getFilesCreated()
72
    {
73
        return $this->filesCreated;
74
    }
75
76
    /**
77
     * @return AbstractSitemap
78
     */
79
    protected function instantiateNewSitemap()
80
    {
81
        return new Sitemap();
82
    }
83
84
    protected function addEntry($entry, Sitemap $sitemap)
85
    {
86
        list($url, $lastmod, $changefreq, $priority) = $this->parseEntry($entry);
87
        $sitemap->add($url, $lastmod, $changefreq, $priority);
88
    }
89
90
    /**
91
     * Generates the sitemap(s) using the iterator previously set.
92
     * @param \Iterator $iterator
93
     * @throws \RuntimeException
94
     * @return string The URL for the entry Sitemap
95
     */
96
    public function createSitemap(Iterator $iterator)
97
    {
98
        $groupName = $this->randomHash();
99
        $paths = new ArrayObject();
100
        $sitemap = $this->instantiateNewSitemap();
101
        foreach ($iterator as $entry) {
102
            if ($sitemap->hasMaxUrlCount()) {
103
                $paths->append($this->writeSitemap($groupName, $sitemap));
104
                $sitemap = $this->instantiateNewSitemap();
105
            }
106
107
            $this->addEntry($entry, $sitemap);
108
        }
109
        $paths->append($this->writeSitemap($groupName, $sitemap));
110
111
        if ($paths->count() > 1) {
112
            return $this->createSitemapIndex($paths->getIterator());
113
        }
114
115
        return $this->fileUrl($paths[0]);
116
    }
117
118
    /**
119
     * Creates a Sitemap index given an Iterator of Sitemaps
120
     * @param Iterator $sitemaps
121
     * @return mixed
122
     */
123
    public function createSitemapIndex(Iterator $sitemaps)
124
    {
125
        $groupName = $this->randomHash();
126
        $sitemapIndexes = new ArrayObject();
127
        $sitemapIndex = new SitemapIndex();
128
        $lastmod = date(DateTime::W3C);
129
        foreach ($sitemaps as $sitemapPath) {
130
            // Ignoring because this is an edge case for HUGE sites...like Facebook.
131
            // @codeCoverageIgnoreStart
132
            if ($sitemapIndex->hasMaxUrlCount()) {
133
                $sitemapIndexes->append($this->writeSitemap($groupName, $sitemapIndex));
134
                $sitemapIndex = new SitemapIndex();
135
            }
136
            // @codeCoverageIgnoreEnd
137
138
            $sitemapIndex->add($this->fileUrl($sitemapPath), $lastmod);
139
        }
140
        $sitemapIndexes->append($this->writeSitemap($groupName, $sitemapIndex));
141
142
        // This will probably never happen, as it would mean over 2.5 Billion URLs in the
143
        // sitemap.  So unless Facebook uses this library, this will never happen, so ignore
144
        // it from code coverage.
145
        // @codeCoverageIgnoreStart
146
        if ($sitemapIndexes->count() > 1) {
147
            return $this->createSitemapIndex($sitemapIndexes->getIterator());
148
        }
149
        // @codeCoverageIgnoreEnd
150
151
        return $this->fileUrl($sitemapIndexes[0]);
152
    }
153
154
    /**
155
     * Writes the given sitemap to the filesystem.  The filename pattern is:
156
     * {MD5_Hash}.{Class_Name}.{Index}.xml
157
     * @param string          $groupName
158
     * @param AbstractSitemap $sitemap
159
     * @return string The filename of the sitemap written
160
     */
161
    protected function writeSitemap($groupName, AbstractSitemap $sitemap)
162
    {
163
        static $index = 0;
164
165
        $className = (new \ReflectionClass($sitemap))->getShortName();
166
        $fileName = "{$groupName}.{$className}.{$index}.xml";
167
        $this->filesystem->write($fileName, $sitemap->toString());
168
        array_push($this->filesCreated, $fileName);
169
        $index++;
170
171
        return $fileName;
172
    }
173
174
    /**
175
     * Parses the given Entry into its constituent parts.
176
     * @param  mixed $entry The entry to parse
177
     * @return array
178
     * @throws \InvalidArgumentException
179
     */
180
    protected function parseEntry($entry)
181
    {
182
        if (!get_property($entry, 'url')) {
183
            throw new \InvalidArgumentException('Url is missing or not accessible.');
184
        }
185
        $url        = get_property($entry, 'url');
186
        $lastmod    = get_property($entry, 'lastmod');
187
        $changefreq = get_property($entry, 'changefreq');
188
        $priority   = get_property($entry, 'priority');
189
190
        return [$url, $lastmod, $changefreq, $priority];
191
    }
192
193
    /**
194
     * Generates a random MD5 hash.
195
     * @return string
196
     * @throws \RuntimeException
197
     */
198
    protected function randomHash()
199
    {
200
        return md5($this->randomBytes(32));
201
    }
202
203
    /**
204
     * Gets the Full URL for the given file.
205
     * @param  string $file
206
     * @return string
207
     */
208
    protected function fileUrl($file)
209
    {
210
        return $this->baseUrl.'/'.ltrim($file, '/');
211
    }
212
213
    /**
214
     * Generates a string of random bytes (of given length).
215
     * @param  integer $bytes The number of bytes to return.
216
     * @throws \RuntimeException
217
     * @return string
218
     * @codeCoverageIgnore
219
     */
220
    protected function randomBytes($bytes = 32)
221
    {
222
        if (extension_loaded('openssl')) {
223
            return openssl_random_pseudo_bytes($bytes);
224
        } elseif (extension_loaded('mcrypt')) {
225
            return mcrypt_create_iv($bytes, MCRYPT_DEV_URANDOM);
226
        }
227
228
        throw new RuntimeException('Extension "openssl" or "mcrypt" is required, but is not installed.');
229
    }
230
}
231