Subversion Repositories oidplus

Rev

Rev 1116 | Rev 1130 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
844 daniel-mar 1
<?php
2
 
3
/*
4
 * OIDplus 2.0
1086 daniel-mar 5
 * Copyright 2019 - 2023 Daniel Marschall, ViaThinkSoft
844 daniel-mar 6
 *
7
 * Licensed under the Apache License, Version 2.0 (the "License");
8
 * you may not use this file except in compliance with the License.
9
 * You may obtain a copy of the License at
10
 *
11
 *     http://www.apache.org/licenses/LICENSE-2.0
12
 *
13
 * Unless required by applicable law or agreed to in writing, software
14
 * distributed under the License is distributed on an "AS IS" BASIS,
15
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
 * See the License for the specific language governing permissions and
17
 * limitations under the License.
18
 */
19
 
1050 daniel-mar 20
namespace ViaThinkSoft\OIDplus;
844 daniel-mar 21
 
1086 daniel-mar 22
// phpcs:disable PSR1.Files.SideEffects
23
\defined('INSIDE_OIDPLUS') or die;
24
// phpcs:enable PSR1.Files.SideEffects
25
 
844 daniel-mar 26
class OIDplusFourCC extends OIDplusObject {
27
        private $fourcc;
28
 
1116 daniel-mar 29
        /**
30
         * FourCC Syntax examples:
31
         * fourcc_transform('8BIM')       === array(56,66,73,77);   // Adobe Photoshop
32
         * fourcc_transform('AVI')        === array(65,86,73,32);   // AVI File (padded with whitespace)
33
         * fourcc_transform('Y3[10][10]') === array(89,51,10,10);   // 10bit Y'CbCr 4:2:2 video
34
         * Non-FourCC:  fourcc_transform returns false.
35
         * @param string $fourcc
36
         * @return array|false
37
         */
38
        private function fourcc_transform(string $fourcc) {
844 daniel-mar 39
                $out = array();
40
                if ($fourcc === '') return false;
41
                for ($i=0; $i<4; $i++) {
42
                        if (strlen($fourcc) === 0) {
43
                                $out[] = 0x20; // fill with whitespace
44
                        } else {
45
                                if ($fourcc[0] !== '[') {
46
                                        $out[] = ord($fourcc[0]);
47
                                        $fourcc = substr($fourcc,1);
48
                                } else {
49
                                        $p = strpos($fourcc,']');
926 daniel-mar 50
                                        $out[] = (int)substr($fourcc,1,$p-1);
844 daniel-mar 51
                                        $fourcc = substr($fourcc,$p+1);
52
                                }
53
                        }
54
                }
55
                if ($fourcc !== '') return false;
56
                return $out;
57
        }
58
 
1116 daniel-mar 59
        /**
60
         * @param $fourcc
61
         */
844 daniel-mar 62
        public function __construct($fourcc) {
63
                if (self::fourcc_transform($fourcc) !== false) {
64
                        $this->fourcc = $fourcc; // leaf node
65
                } else {
66
                        $this->fourcc = $fourcc; // It is a category name
67
                }
68
        }
69
 
1116 daniel-mar 70
        /**
71
         * @param string $node_id
72
         * @return OIDplusFourCC|null
73
         */
74
        public static function parse(string $node_id)/*: ?OIDplusFourCC*/ {
844 daniel-mar 75
                @list($namespace, $fourcc) = explode(':', $node_id, 2);
1116 daniel-mar 76
                if ($namespace !== self::ns()) return null;
844 daniel-mar 77
                return new self($fourcc);
78
        }
79
 
1116 daniel-mar 80
        /**
81
         * @return string
82
         */
83
        public static function objectTypeTitle(): string {
844 daniel-mar 84
                return _L('Four-Character-Code (FourCC)');
85
        }
86
 
1116 daniel-mar 87
        /**
88
         * @return string
89
         */
90
        public static function objectTypeTitleShort(): string {
844 daniel-mar 91
                return _L('FourCC');
92
        }
93
 
1116 daniel-mar 94
        /**
95
         * @return string
96
         */
97
        public static function ns(): string {
844 daniel-mar 98
                return 'fourcc';
99
        }
100
 
1116 daniel-mar 101
        /**
102
         * @return string
103
         */
104
        public static function root(): string {
860 daniel-mar 105
                return self::ns().':';
844 daniel-mar 106
        }
107
 
1116 daniel-mar 108
        /**
109
         * @return bool
110
         */
111
        public function isRoot(): bool {
844 daniel-mar 112
                return $this->fourcc == '';
113
        }
114
 
1116 daniel-mar 115
        /**
116
         * @param bool $with_ns
117
         * @return string
118
         */
119
        public function nodeId(bool $with_ns=true): string {
859 daniel-mar 120
                return $with_ns ? self::root().$this->fourcc : $this->fourcc;
844 daniel-mar 121
        }
122
 
1116 daniel-mar 123
        /**
124
         * @param string $str
125
         * @return string
126
         */
127
        public function addString(string $str): string {
845 daniel-mar 128
 
129
                // Y3[10] [10] --> Y3[10][10]
130
                $test_str = trim($str);
131
                do {
132
                        $test_str2 = $test_str;
133
                        $test_str = str_replace(' [', '[', $test_str);
134
                        $test_str = str_replace('] ', ']', $test_str);
135
                } while ($test_str2 != $test_str);
136
 
137
                if (self::fourcc_transform($test_str) !== false) {
844 daniel-mar 138
                        // real FourCC
858 daniel-mar 139
                        return self::root() . $test_str;
844 daniel-mar 140
                } else {
141
                        // just a category
858 daniel-mar 142
                        if ($this->isRoot()) {
143
                                return self::root() . $str;
144
                        } else {
145
                                return $this->nodeId() . '/' . $str;
146
                        }
844 daniel-mar 147
                }
148
        }
149
 
1116 daniel-mar 150
        /**
151
         * @param OIDplusObject $parent
152
         * @return string
153
         */
154
        public function crudShowId(OIDplusObject $parent): string {
850 daniel-mar 155
                if ($this->isLeafNode()) {
156
                        // We don't parse '/' in a valid FourCC code (i.e. Leaf node)
157
                        return $this->nodeId(false);
158
                } else {
159
                        if ($parent->isRoot()) {
160
                                return substr($this->nodeId(), strlen($parent->nodeId()));
161
                        } else {
162
                                return substr($this->nodeId(), strlen($parent->nodeId())+1);
163
                        }
164
                }
844 daniel-mar 165
        }
166
 
1116 daniel-mar 167
        /**
168
         * @param OIDplusObject|null $parent
169
         * @return string
170
         */
171
        public function jsTreeNodeName(OIDplusObject $parent = null): string {
844 daniel-mar 172
                if ($parent == null) return $this->objectTypeTitle();
173
                return $this->crudShowId($parent);
174
        }
175
 
1116 daniel-mar 176
        /**
177
         * @return string
178
         */
179
        public function defaultTitle(): string {
844 daniel-mar 180
                return $this->fourcc;
181
        }
182
 
1116 daniel-mar 183
        /**
184
         * @return bool
185
         */
186
        public function isLeafNode(): bool {
844 daniel-mar 187
                return self::fourcc_transform($this->fourcc) !== false;
188
        }
189
 
1116 daniel-mar 190
        /**
191
         * @return array
192
         */
193
        private function getTechInfo(): array {
844 daniel-mar 194
                $tech_info = array();
845 daniel-mar 195
                $tech_info[_L('FourCC code')]   = $this->fourcc;
196
                $tech_info[_L('C/C++ Literal')] = $this->getMultiCharLiteral();
844 daniel-mar 197
                $tech_info[_L('Hex Dump')]      = strtoupper(implode(' ', str_split($this->getHex(true),2)));
1054 daniel-mar 198
                $tech_info[_L('Big Endian')]    = '0x'.$this->getHex(true).' ('.$this->getInt(true).')';
199
                $tech_info[_L('Little Endian')] = '0x'.$this->getHex(false).' ('.$this->getInt(false).')';
844 daniel-mar 200
                return $tech_info;
201
        }
202
 
1116 daniel-mar 203
        /**
204
         * @param string $title
205
         * @param string $content
206
         * @param string $icon
207
         * @return void
208
         * @throws OIDplusException
209
         */
210
        public function getContentPage(string &$title, string &$content, string &$icon) {
844 daniel-mar 211
                $icon = file_exists(__DIR__.'/img/main_icon.png') ? OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'img/main_icon.png' : '';
212
 
213
                if ($this->isRoot()) {
214
                        $title = OIDplusFourCC::objectTypeTitle();
215
 
216
                        $res = OIDplus::db()->query("select * from ###objects where parent = ?", array(self::root()));
217
                        if ($res->any()) {
962 daniel-mar 218
                                $content  = '<p>'._L('Please select a FourCC in the tree view at the left to show its contents.').'</p>';
844 daniel-mar 219
                        } else {
962 daniel-mar 220
                                $content  = '<p>'._L('Currently, no FourCC is registered in the system.').'</p>';
844 daniel-mar 221
                        }
222
 
223
                        if (!$this->isLeafNode()) {
224
                                if (OIDplus::authUtils()->isAdminLoggedIn()) {
225
                                        $content .= '<h2>'._L('Manage root objects / categories').'</h2>';
226
                                } else {
227
                                        $content .= '<h2>'._L('Available objects / categories').'</h2>';
228
                                }
229
                                $content .= '%%CRUD%%';
230
                        }
231
                } else {
232
                        $title = $this->getTitle();
233
 
234
                        if ($this->isLeafNode()) {
235
                                $tech_info = $this->getTechInfo();
236
                                $tech_info_html = '';
237
                                if (count($tech_info) > 0) {
238
                                        $tech_info_html .= '<h2>'._L('Technical information').'</h2>';
239
                                        $tech_info_html .= '<table border="0">';
240
                                        foreach ($tech_info as $key => $value) {
241
                                                $tech_info_html .= '<tr><td>'.$key.': </td><td><code>'.str_replace(' ','&nbsp;',$value).'</code></td></tr>';
242
                                        }
243
                                        $tech_info_html .= '</table>';
244
                                }
245
 
246
                                $content = $tech_info_html;
247
                        } else {
248
                                $content = '';
249
                        }
250
 
251
                        $content .= '<h2>'._L('Description').'</h2>%%DESC%%';
252
 
253
                        if (!$this->isLeafNode()) {
254
                                if ($this->userHasWriteRights()) {
928 daniel-mar 255
                                        $content .= '<h2>'._L('Create or change subordinate objects / categories').'</h2>';
844 daniel-mar 256
                                } else {
928 daniel-mar 257
                                        $content .= '<h2>'._L('Subordinate objects / categories').'</h2>';
844 daniel-mar 258
                                }
259
                                $content .= '%%CRUD%%';
260
                        }
261
                }
262
        }
263
 
1116 daniel-mar 264
        /**
265
         * @return OIDplusFourCC|null
266
         */
267
        public function one_up()/*: ?OIDplusFourCC*/ {
844 daniel-mar 268
                // A FourCC is a FourCC, there is no hierarchy
1116 daniel-mar 269
                return null;
844 daniel-mar 270
        }
271
 
1116 daniel-mar 272
        /**
273
         * @param $to
274
         * @return null
275
         */
844 daniel-mar 276
        public function distance($to) {
277
                // Distance between FourCCs is not possible
278
                return null;
279
        }
280
 
1116 daniel-mar 281
        /**
282
         * @return array|OIDplusAltId[]
283
         * @throws OIDplusException
284
         */
285
        public function getAltIds(): array {
844 daniel-mar 286
                if ($this->isRoot()) return array();
287
                if (!$this->isLeafNode()) return array();
288
                $ids = parent::getAltIds();
289
                return $ids;
290
        }
291
 
1116 daniel-mar 292
        /**
293
         * @param $big_endian
294
         * @return false|int|mixed
295
         */
1054 daniel-mar 296
        private function getInt($big_endian) {
844 daniel-mar 297
                $type = self::fourcc_transform($this->fourcc);
298
                if ($type === false) return false;
299
                $dec = 0;
300
                if (!$big_endian) $type = array_reverse($type);
301
                for ($i=0;$i<4;$i++) $dec = ($dec<<8) + $type[$i];
1054 daniel-mar 302
                return $dec;
303
        }
304
 
1116 daniel-mar 305
        /**
306
         * @param $big_endian
307
         * @return string
308
         */
1054 daniel-mar 309
        private function getHex($big_endian) {
310
                $dec = $this->getInt($big_endian);
844 daniel-mar 311
                $hex = str_pad(dechex($dec), 8, "0", STR_PAD_LEFT);
312
                return $hex;
313
        }
314
 
1116 daniel-mar 315
        /**
316
         * @return false|string
317
         */
845 daniel-mar 318
        private function getMultiCharLiteral() {
844 daniel-mar 319
                $type = self::fourcc_transform($this->fourcc);
320
                if ($type === false) return false;
926 daniel-mar 321
                return c_literal($type);
844 daniel-mar 322
        }
323
 
1116 daniel-mar 324
        /**
325
         * @return string
326
         * @throws OIDplusException
327
         */
328
        public function getDirectoryName(): string {
844 daniel-mar 329
                if ($this->isLeafNode()) {
330
                        // Leaf (FourCC)
331
                        // Example output: "fourcc_23496d52" for 'fourcc:#ImR'
332
                        return $this->ns().'_'.$this->getHex(true);
333
                } else {
334
                        // Category
335
                        return parent::getDirectoryName();
336
                }
337
        }
338
 
1116 daniel-mar 339
        /**
340
         * @param string $mode
341
         * @return string
342
         */
343
        public static function treeIconFilename(string $mode): string {
844 daniel-mar 344
                return 'img/'.$mode.'_icon16.png';
345
        }
850 daniel-mar 346
}