๐Ÿ“ฆ directus / v6-archive

๐Ÿ“„ JsonView.php ยท 155 lines
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155<?php

namespace Directus\View;

use Directus\Bootstrap;

/**
 * @todo  Could be implemented as middleware.
 */
class JsonView
{

    /**
     * @var callable
     */
    public static $preDispatch;

    /**
     * Pass a closure to this function in order to modify the output data
     * before it is json_encoded and sent to the client. The callable should
     * accept an array parameter, and return the modified array.
     * @param  callable $callable
     * @return null
     */
    public static function preDispatch($callable)
    {
        if (!is_callable($callable)) {
            throw new \InvalidArgumentException(__t('predispatch_callable_must_be_callable'));
        }
        self::$preDispatch = $callable;
    }

    /**
     * @param  array|\JsonSerializable $responseData The new API layer's response.
     * @param  array $responseDataComparison The old API layer's response
     * @return null
     * @todo only format JSON for non-prod environments when DIRECTUS_ENV
     * is available
     */
    public static function render($responseData, $responseDataComparison = null)
    {
        if (!is_array($responseData) && !$responseData instanceof \JsonSerializable) {
            $message = sprintf('JsonView::render - ResponseData must be of the type array or JsonSerializable, %s given', [
                gettype($responseData)
            ]);
            throw new \InvalidArgumentException($message);
        }

        if (!is_null(self::$preDispatch)) {
            $preDispatch = self::$preDispatch;
            $responseData = $preDispatch($responseData);
        }
        $responseData = json_encode($responseData);
        if ('production' !== DIRECTUS_ENV) { // e.g. 'production' !== DIRECTUS_ENV
            //$responseData = self::format_json($responseData);
            //$responseData .= "\n";
        }

        /**
         * TRANSITIONAL - Do comparison between two possible responses, the old
         * DB layer response data and the new.
         */
        if (!is_null($responseDataComparison)) {
            self::compareApiResponses($responseData, $responseDataComparison);
        }

        echo $responseData;
    }

    public static function compareApiResponses($new, $old)
    {
        $id = time();
        $old = self::format_json(json_encode($old));
        $log = Bootstrap::get('app')->getLog();
        $uri = $_SERVER['REQUEST_URI'];
        if (0 === strcmp($new, $old))
            return $log->info('The response comparison matched. [' . $uri . ']');
        $log->warn('The response comparison failed. [' . $uri . ']');
        // Output path
        $fname_prefix = 'cmp_' . $id;
        $dir = APPLICATION_PATH . '/docs/api-responses';
        if (!is_dir($dir)) {
            $log->fatal('Can\'t write API responses to output directory: ' . $dir);
            return;
        }
        // Write API responses to disk
        foreach (['new', 'old'] as $version) {
            $fname = $fname_prefix . '_' . $version . '.json';
            $fpath = $dir . '/' . $fname;
            $fp = fopen($fpath, 'w+');
            fwrite($fp, $$version);
            fclose($fp);
            $log->info('Wrote $version API response version to ' . $fpath);
        }
    }

    /**
     * Indents a flat JSON string to make it more human-readable.
     * @param string $json The original JSON string to process.
     * @return string Indented version of the original JSON string.
     */
    public static function format_json($json)
    {

        $result = '';
        $pos = 0;
        $strLen = strlen($json);
        $indentStr = '  ';
        $newLine = "\n";
        $prevChar = '';
        $outOfQuotes = true;

        for ($i = 0; $i <= $strLen; $i++) {

            // Grab the next character in the string.
            $char = substr($json, $i, 1);

            // Are we inside a quoted string?
            if ($char == '"' && $prevChar != '\\') {
                $outOfQuotes = !$outOfQuotes;

                // If this character is the end of an element,
                // output a new line and indent the next line.
            } else if (($char == '}' || $char == ']') && $outOfQuotes) {
                $result .= $newLine;
                $pos--;
                for ($j = 0; $j < $pos; $j++) {
                    $result .= $indentStr;
                }
            }

            // Add the character to the result string.
            $result .= $char;

            // If the last character was the beginning of an element,
            // output a new line and indent the next line.
            if (($char == ',' || $char == '{' || $char == '[') && $outOfQuotes) {
                $result .= $newLine;
                if ($char == '{' || $char == '[') {
                    $pos++;
                }

                for ($j = 0; $j < $pos; $j++) {
                    $result .= $indentStr;
                }
            }

            $prevChar = $char;
        }

        return $result;
    }

}