1<?php
2
3namespace LesserPHP\Functions;
4
5use Exception;
6use LesserPHP\Utils\Asserts;
7use LesserPHP\Utils\Util;
8
9/**
10 * Implements the  miscellaneous functions for LESS
11 *
12 * @link https://lesscss.org/functions/#misc-functions
13 */
14class Misc extends AbstractFunctionCollection
15{
16    /** @inheritdoc */
17    public function getFunctions(): array
18    {
19        return [
20            //'color' => [$this, 'color'],
21            //'image-size' => [$this, 'imageSize'],
22            //'image-width' => [$this, 'imageWidth'],
23            //'image-height' => [$this, 'imageHeight'],
24            'convert' => [$this, 'convert'],
25            'data-uri' => [$this, 'dataUri'],
26            //'default' => [$this, 'default'],
27            'unit' => [$this, 'unit'],
28            //'get-unit' => [$this, 'getUnit'],
29            //'svg-gradient' => [$this, 'svgGradient'],
30        ];
31    }
32
33    // color is missing
34    // image-size is missing
35    // image-width is missing
36    // image-height is missing
37
38    /**
39     * Convert a number from one unit into another
40     *
41     * @link https://lesscss.org/functions/#misc-functions-convert
42     * @throws Exception
43     */
44    public function convert(array $args): array
45    {
46        [$value, $to] = Asserts::assertArgs($args, 2, 'convert');
47
48        // If it's a keyword, grab the string version instead
49        if (is_array($to) && $to[0] == 'keyword') {
50            $to = $to[1];
51        }
52
53        return Util::convert($value, $to);
54    }
55
56    /**
57     * Given an url, decide whether to output a regular link or the base64-encoded contents of the file
58     *
59     * @param array $value either an argument list (two strings) or a single string
60     * @return string        formatted url(), either as a link or base64-encoded
61     */
62    public function dataUri(array $value): string
63    {
64        $mime = ($value[0] === 'list') ? $value[2][0][2] : null;
65        $url = ($value[0] === 'list') ? $value[2][1][2][0] : $value[2][0];
66
67        $fullpath = $this->lessc->findImport($url);
68
69        if ($fullpath && ($fsize = filesize($fullpath)) !== false) {
70            // IE8 can't handle data uris larger than 32KB
71            if ($fsize / 1024 < 32) {
72                if (is_null($mime)) {
73                    if (class_exists('finfo')) { // php 5.3+
74                        $finfo = new \finfo(FILEINFO_MIME);
75                        $mime = explode('; ', $finfo->file($fullpath));
76                        $mime = $mime[0];
77                    } elseif (function_exists('mime_content_type')) { // PHP 5.2
78                        $mime = mime_content_type($fullpath);
79                    }
80                }
81
82                if (!is_null($mime)) // fallback if the mime type is still unknown
83                    $url = sprintf('data:%s;base64,%s', $mime, base64_encode(file_get_contents($fullpath)));
84            }
85        }
86
87        return 'url("' . $url . '")';
88    }
89
90    // default is missing
91
92
93    /**
94     * Remove or change the unit of a dimension
95     *
96     * @link https://lesscss.org/functions/#misc-functions-unit
97     * @throws Exception
98     */
99    public function unit(array $arg): array
100    {
101        if ($arg[0] == 'list') {
102            [$number, $newUnit] = $arg[2];
103            return [
104                'number',
105                Asserts::assertNumber($number),
106                $this->lessc->compileValue($this->lessc->unwrap($newUnit))
107            ];
108        } else {
109            return ['number', Asserts::assertNumber($arg), ''];
110        }
111    }
112
113    // get-unit is missing
114    // svg-gradient is missing
115}
116