Passed
Pull Request — master (#25)
by Matthew
09:19 queued 03:23
created

ColumnUtil::populateCacheFile()   B

Complexity

Conditions 9
Paths 8

Size

Total Lines 35
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 26
c 1
b 0
f 0
dl 0
loc 35
rs 8.0555
cc 9
nc 8
nop 2
1
<?php
2
3
namespace Dtc\GridBundle\Util;
4
5
use Dtc\GridBundle\Annotation\Action;
6
use Symfony\Component\Yaml\Yaml;
0 ignored issues
show
Bug introduced by
The type Symfony\Component\Yaml\Yaml was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
7
use Exception;
8
9
class ColumnUtil
10
{
11
    /**
12
     * @param $cacheDir
13
     * @param $fqn
14
     *
15
     * @return string
16
     *
17
     * @throws Exception
18
     */
19
    public static function createCacheFilename($cacheDir, $fqn)
20
    {
21
        $directory = $cacheDir.'/DtcGridBundle';
22
        $umask = decoct(umask());
23
        $umask = str_pad($umask, 4, '0', STR_PAD_LEFT);
24
25
        // Is there a better way to do this?
26
        $permissions = '0777';
27
        $permissions[1] = intval($permissions[1]) - intval($umask[1]);
28
        $permissions[2] = intval($permissions[2]) - intval($umask[2]);
29
        $permissions[3] = intval($permissions[3]) - intval($umask[3]);
30
31
        $name = str_replace('\\', DIRECTORY_SEPARATOR, $fqn);
32
        $name = ltrim($name, DIRECTORY_SEPARATOR);
33
        $filename = $directory.DIRECTORY_SEPARATOR.$name.'.php';
34
35
        if (($dir = dirname($filename)) && !is_dir($dir) && !mkdir($dir, octdec($permissions), true)) {
0 ignored issues
show
Bug introduced by
It seems like octdec($permissions) can also be of type double; however, parameter $mode of mkdir() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

35
        if (($dir = dirname($filename)) && !is_dir($dir) && !mkdir($dir, /** @scrutinizer ignore-type */ octdec($permissions), true)) {
Loading history...
36
            throw new Exception("Can't create: ".$dir);
37
        }
38
        if (!is_writable($dir)) {
39
            throw new Exception("Can't write to: $dir");
40
        }
41
42
        return $filename;
43
    }
44
45
    /**
46
     * @param string $filename
47
     * @param array  $classInfo
48
     */
49
    public static function populateCacheFile($filename, array $classInfo)
50
    {
51
        $columns = isset($classInfo['columns']) ? $classInfo['columns'] : [];
52
        $sort = isset($classInfo['sort']) ? $classInfo['sort'] : [];
53
54
        if ($columns) {
55
            $output = "<?php\nreturn array('columns' => array(\n";
56
            foreach ($columns as $field => $info) {
57
                $class = $info['class'];
58
                $output .= "'$field' => new $class(";
59
                $first = true;
60
                foreach ($info['arguments'] as $argument) {
61
                    if ($first) {
62
                        $first = false;
63
                    } else {
64
                        $output .= ',';
65
                    }
66
                    $output .= var_export($argument, true);
67
                }
68
                $output .= '),';
69
            }
70
            $output .= "), 'sort' => array(";
71
            foreach ($sort as $key => $value) {
72
                $output .= "'$key'".' => ';
73
                if (null === $value) {
74
                    $output .= 'null,';
75
                } else {
76
                    $output .= "'$value',";
77
                }
78
            }
79
            $output .= "));\n";
80
        } else {
81
            $output = "<?php\nreturn false;\n";
82
        }
83
        file_put_contents($filename, $output);
84
    }
85
86
    /**
87
     * @param string $cacheDir
88
     * @param string $filename
89
     *
90
     * @throws Exception
91
     */
92
    public static function cacheClassesFromFile($cacheDir, $filename)
93
    {
94
        $classes = self::extractClassesFromFile($filename);
95
        foreach ($classes as $class => $columnInfo) {
96
            $filename = ColumnUtil::createCacheFilename($cacheDir, $class);
97
            self::populateCacheFile($filename, $columnInfo);
98
        }
99
    }
100
101
    /**
102
     * @param string $filename
103
     *
104
     * @return array
105
     *
106
     * @throws Exception
107
     */
108
    public static function extractClassesFromFile($filename)
109
    {
110
        // @TODO probably break this into multiple functions
111
        if (!is_readable($filename)) {
112
            throw new Exception("Can't read {$filename}");
113
        }
114
        $stat = stat($filename);
115
        $result = Yaml::parseFile($filename);
116
        if (!$result && $stat['size'] > 0) {
117
            throw new Exception("Can't parse data from {$filename}");
118
        }
119
120
        $classes = [];
121
        foreach ($result as $class => $info) {
122
            if (!isset($info['columns'])) {
123
                // @TODO some kind of warning here - or try to read using reflection?
124
                continue;
125
            }
126
            $class = ltrim($class, '\\');
127
            if (!class_exists($class)) {
128
                throw new Exception("$class - class does not exist");
129
            }
130
            $classes[$class]['columns'] = [];
131
            foreach ($info['columns'] as $name => $columnDef) {
132
                $label = isset($columnDef['label']) ? $columnDef['label'] : CamelCase::fromCamelCase($name);
133
                $column = ['class' => '\Dtc\GridBundle\Grid\Column\GridColumn', 'arguments' => [$name, $label]];
134
                $column['arguments'][] = isset($columnDef['formatter']) ? $columnDef['formatter'] : null;
135
                if (isset($columnDef['sortable'])) {
136
                    $column['arguments'][] = ['sortable' => $columnDef['sortable'] ? true : false];
137
                } else {
138
                    $column['arguments'][] = [];
139
                }
140
                $column['arguments'][] = isset($columnDef['searchable']) ? ($columnDef['searchable'] ? true : false) : false;
141
                $column['arguments'][] = null;
142
                $classes[$class]['columns'][$name] = $column;
143
            }
144
145
            if (isset($info['actions'])) {
146
                $field = '\$-action';
147
                $actionArgs = [$field];
148
                $actionDefs = [];
149
                /* @var Action $action */
150
                foreach ($info['actions'] as $action) {
151
                    if (!isset($action['label'])) {
152
                        throw new Exception("$class - action definition missing 'label' ".print_r($action, true));
153
                    }
154
                    if (!isset($action['route'])) {
155
                        throw new Exception("$class - action definition missing 'route' ".print_r($action, true));
156
                    }
157
                    if (!isset($action['type'])) {
158
                        throw new Exception("$class - action definition missing 'type' ".print_r($action, true));
159
                    }
160
                    $actionDef = ['label' => $action['label'], 'route' => $action['route']];
161
                    switch ($action['type']) {
162
                        case 'show':
163
                            $actionDef['action'] = 'show';
164
                            break;
165
                        case 'delete':
166
                            $actionDef['action'] = 'delete';
167
                            break;
168
                        default:
169
                            throw new Exception("$class - action definition unknown 'type' {$action['type']} ".print_r($action, true));
170
                    }
171
                    $actionDefs[] = $actionDef;
172
                }
173
                $actionArgs[] = $actionDefs;
174
                $classes[$class]['columns'][$field] = ['class' => '\Dtc\GridBundle\Grid\Column\ActionGridColumn', 'arguments' => $actionArgs];
175
            }
176
            if (isset($info['sort'])) {
177
                foreach ($info['sort'] as $key => $value) {
178
                    if (!isset($info['columns'][$key])) {
179
                        throw new Exception("$class - can't find sort column $key in list of columns.");
180
                    }
181
                    switch ($value) {
182
                        case 'ASC':
183
                            break;
184
                        case 'DESC':
185
                            break;
186
                        default:
187
                            throw new Exception("$class - sort type should be ASC or DESC instead of $value.");
188
                    }
189
                }
190
                $classes[$class]['sort'] = $info['sort'];
191
            }
192
        }
193
194
        return $classes;
195
    }
196
}
197