Completed
Push — master ( 373d93...1d945d )
by Joschi
02:53
created

AbstractTest::scanTemporaryDirectory()   B

Complexity

Conditions 6
Paths 4

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 6
eloc 7
c 1
b 0
f 0
nc 4
nop 1
dl 0
loc 12
rs 8.8571
1
<?php
2
3
/**
4
 * apparat-dev
5
 *
6
 * @category    Apparat
7
 * @package     Apparat\Dev
8
 * @subpackage  Apparat\Dev\Tests
9
 * @author      Joschi Kuphal <[email protected]> / @jkphl
10
 * @copyright   Copyright © 2016 Joschi Kuphal <[email protected]> / @jkphl
11
 * @license     http://opensource.org/licenses/MIT The MIT License (MIT)
12
 */
13
14
/***********************************************************************************
15
 *  The MIT License (MIT)
16
 *
17
 *  Copyright © 2016 Joschi Kuphal <[email protected]> / @jkphl
18
 *
19
 *  Permission is hereby granted, free of charge, to any person obtaining a copy of
20
 *  this software and associated documentation files (the "Software"), to deal in
21
 *  the Software without restriction, including without limitation the rights to
22
 *  use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
23
 *  the Software, and to permit persons to whom the Software is furnished to do so,
24
 *  subject to the following conditions:
25
 *
26
 *  The above copyright notice and this permission notice shall be included in all
27
 *  copies or substantial portions of the Software.
28
 *
29
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
30
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
31
 *  FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
32
 *  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
33
 *  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
34
 *  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35
 ***********************************************************************************/
36
37
namespace Apparat\Dev\Tests;
38
39
/**
40
 * Basic tests for generic files
41
 *
42
 * @package     Apparat\Dev
43
 * @subpackage  Apparat\Dev\Tests
44
 */
45
abstract class AbstractTest extends \PHPUnit_Framework_TestCase
46
{
47
    /**
48
     * Temporary files
49
     *
50
     * @var array
51
     */
52
    protected $tmpFiles = [];
53
    /**
54
     * Temporary directories
55
     *
56
     * @var array
57
     */
58
    protected $tmpDirectories = [];
59
60
    /**
61
     * Tests if two arrays equal in their keys and values
62
     *
63
     * @param array $expected Expected result
64
     * @param array $actual Actual result
65
     * @param string $message Message
66
     */
67
    public function assertArrayEquals(array $expected, array $actual, $message = '')
68
    {
69
        $this->assertEquals(
70
            $this->sortArrayForComparison($expected),
71
            $this->sortArrayForComparison($actual),
72
            $message
73
        );
74
    }
75
76
    /**
77
     * Recursively sort an array for comparison with another array
78
     *
79
     * @param array $array Array
80
     * @return array                Sorted array
81
     */
82
    protected function sortArrayForComparison(array $array)
83
    {
84
        // Tests if all array keys are numeric
85
        $allNumeric = true;
86
        foreach (array_keys($array) as $key) {
87
            if (!is_numeric($key)) {
88
                $allNumeric = false;
89
                break;
90
            }
91
        }
92
93
        // If not all keys are numeric: Sort the array by key
94
        if (!$allNumeric) {
95
            ksort($array, SORT_STRING);
96
            return $this->sortArrayRecursive($array);
97
        }
98
99
        // Sort them by data type and value
100
        $array = $this->sortArrayRecursive($array);
101
        usort(
102
            $array,
103
            function (
104
                $first,
105
                $second
106
            ) {
107
                $aType = gettype($first);
108
                $bType = gettype($second);
109
                if ($aType === $bType) {
110
                    switch ($aType) {
111
                        case 'array':
112
                            return strcmp(implode('', array_keys($first)), implode('', array_keys($second)));
113
                        case 'object':
114
                            return strcmp(spl_object_hash($first), spl_object_hash($second));
115
                        default:
116
                            return strcmp(strval($first), strval($second));
117
                    }
118
                }
119
120
                return strcmp($aType, $bType);
121
            }
122
        );
123
124
        return $array;
125
    }
126
127
    /**
128
     * Recursively sort an array for comparison
129
     *
130
     * @param array $array Original array
131
     * @return array Sorted array
132
     */
133
    protected function sortArrayRecursive(array $array)
134
    {
135
136
        // Run through all elements and sort them recursively if they are an array
137
        reset($array);
138
        while (list($key, $value) = each($array)) {
139
            if (is_array($value)) {
140
                $array[$key] = $this->sortArrayForComparison($value);
141
            }
142
        }
143
144
        return $array;
145
    }
146
147
    /**
148
     * Tears down the fixture
149
     */
150
    protected function tearDown()
151
    {
152
        foreach ($this->tmpDirectories as $tmpDirectory) {
153
            $this->scanTemporaryDirectory($tmpDirectory);
154
        }
155
        foreach (array_reverse($this->tmpFiles) as $tmpFile) {
156
            @is_file($tmpFile) ? @unlink($tmpFile) : @rmdir($tmpFile);
157
        }
158
    }
159
160
    /**
161
     * Prepare and register a temporary file name
162
     *
163
     * @return string Temporary file name
164
     */
165
    protected function createTemporaryFileName()
166
    {
167
        $tempFileName = $this->createTemporaryFile();
168
        unlink($tempFileName);
169
        return $tempFileName;
170
    }
171
172
    /**
173
     * Prepare and register a temporary file
174
     *
175
     * @return string Temporary file name
176
     */
177
    protected function createTemporaryFile()
178
    {
179
        return $this->tmpFiles[] = tempnam(sys_get_temp_dir(), 'apparat_test_');
180
    }
181
182
    /**
183
     * Register a temporary directory that needs to be deleted recursively on shutdown
184
     *
185
     * @param string $directory Directory
186
     * @return string Directory
187
     */
188
    protected function registerTemporaryDirectory($directory)
189
    {
190
        return $this->tmpDirectories[] = $this->tmpFiles[] = $directory;
191
    }
192
193
    /**
194
     * Scan a temporary directory and register all files and subdirectories (recursively)
195
     *
196
     * @param string $directory Directory
197
     */
198
    protected function scanTemporaryDirectory($directory)
199
    {
200
        foreach (scandir($directory) as $fileOrDirectory) {
201
            if ($fileOrDirectory !== '.' && $fileOrDirectory !== '..' && !is_link($fileOrDirectory)) {
202
                $fileOrDirectory = $directory.DIRECTORY_SEPARATOR.$fileOrDirectory;
203
                $this->tmpFiles[] = $fileOrDirectory;
204
                if (is_dir($fileOrDirectory)) {
205
                    $this->scanTemporaryDirectory($fileOrDirectory);
206
                }
207
            }
208
        }
209
    }
210
211
    /**
212
     * Normalize HTML contents
213
     *
214
     * @param string $html Original HTML
215
     * @return string Normalized HTML
216
     */
217
    protected function normalizeHtml($html)
218
    {
219
        $htmlDom = new \DOMDocument();
220
        $htmlDom->preserveWhiteSpace = false;
221
        $htmlDom->formatOutput = false;
222
        $htmlDom->loadXML("<html><head><title>apparat</title></head><body>$html</body></html>");
223
        return $htmlDom->saveXML();
224
    }
225
}
226