TagFactory::runHandler()   A
last analyzed

Complexity

Conditions 5
Paths 4

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 5.0488

Importance

Changes 0
Metric Value
eloc 7
dl 0
loc 12
ccs 7
cts 8
cp 0.875
rs 9.6111
c 0
b 0
f 0
cc 5
nc 4
nop 4
crap 5.0488
1
<?php
2
3
namespace Dallgoot\Yaml\Tag;
4
5
use Dallgoot\Yaml\Nodes\Generic\NodeGeneric;
6
use Dallgoot\Yaml\NodeList;
7
use Dallgoot\Yaml\Regex;
8
use Dallgoot\Yaml\Tag\CoreSchema;
9
10
/**
11
 * Provides mechanisms to handle tags
12
 * - registering tags and their handler methods
13
 * - returning transformed values according to Node type or NodeList
14
 *
15
 * Note: currently supports ONLY local tags
16
 *
17
 * @author  Stéphane Rebai <[email protected]>
18
 * @license Apache 2.0
19
 * @link    https://github.com/dallgoot/yaml
20
 *
21
 * @todo move legacy tags handlers in a specific class : checking affecting methods to tags mechanisms when theres a global tag
22
 */
23
class TagFactory
24
{
25
    private const UNKNOWN_TAG = 'Error: tag "%s" is unknown (have you registered a handler for it? see Dallgoot\Yaml\Tag\SchemaInterface)';
26
    private const NO_NAME     = '%s Error: a tag MUST have a name';
27
    private const WRONG_VALUE = "Error : cannot transform tag '%s' for type '%s'";
28
    private const ERROR_HANDLE_EXISTS = "This tag handle is already registered, did you use a named handle like '!name!' ?";
29
30
    public static $schemas = [];
31
    public static $schemaHandles = [];
32
    /**
33
 The primary tag handle is a single “!” character.
34
 # Global
35
%TAG ! tag:example.com,2000:app/
36
---
37
!foo "bar"
38
39
 The secondary tag handle is written as “!!”. This allows using a compact notation for a single “secondary” name space. By default, the prefix associated with this handle is “tag:yaml.org,2002:”. This prefix is used by the YAML tag repository.
40
 %TAG !! tag:example.com,2000:app/
41
---
42
!!int 1 - 3 # Interval, not integer
43
44
45
Named Handles
46
47
    A named tag handle surrounds a non-empty name with “!” characters. A handle name must not be used in a tag shorthand unless an explicit “TAG” directive has associated some prefix with it.
48
49
    The name of the handle is a presentation detail and must not be used to convey content information. In particular, the YAML processor need not preserve the handle name once parsing is completed.
50
51
52
53
Verbatim Tags
54
    A tag may be written verbatim by surrounding it with the “<” and “>” characters. In this case, the YAML processor must deliver the verbatim tag as-is to the application. In particular, verbatim tags are not subject to tag resolution. A verbatim tag must either begin with a “!” (a local tag) or be a valid URI (a global tag).
55
56
57
  !<!bar> baz
58
59
60
%TAG !e! tag:example.com,2000:app/
61
---
62
!e!foo "bar"
63
64
%TAG ! tag:example.com,2000:app/
65
%TAG !! tag:example.com,2000:app/
66
%TAG !e! tag:example.com,2000:app/
67
!<tag:yaml.org,2002:str> foo :
68
69
     */
70
    /**
71
     * Add Handlers for legacy Yaml tags
72
     *
73
     * @see self::LEGACY_TAGS_HANDLERS
74
     * @todo remove dependency to ReflectionClass using 'get_class_methods'
75
     */
76 1
    private static function createCoreSchema()
77
    {
78 1
        $coreSchema = new CoreSchema;
79 1
        self::registerSchema($coreSchema::SCHEMA_URI, $coreSchema);
80 1
        self::registerHandle("!!", $coreSchema::SCHEMA_URI);
81
    }
82
83 2
    public static function registerSchema($URI, SchemaInterface $schemaObject)
84
    {
85 2
        self::$schemas[$URI] = $schemaObject;
86
    }
87
88 2
    public static function registerHandle(string $handle, string $prefixOrURI)
89
    {
90 2
        if (array_key_exists($handle, self::$schemaHandles)) {
91
            throw new \Exception(self::ERROR_HANDLE_EXISTS, 1);
92
        }
93 2
        self::$schemaHandles[$handle] = $prefixOrURI;
94
    }
95
96
    /**
97
     * transform a Node type based on the tag ($identifier) provided
98
     *
99
     * @param      string      $identifier  The identifier
100
     * @param      mixed      $value       The value
101
     *
102
     * @throws     \Exception  Raised if the Tag $identifier is unknown (= not in TagDefault nor registered by user)
103
     *
104
     * @return     mixed      If $value can be preserved as Node type :the same Node type,
105
     *                        otherwise any type that the tag transformation returns
106
     */
107 1
    public static function transform(string $identifier, $value, &$parent = null)
108
    {
109 1
        if (count(self::$schemas) === 0) {
110
            self::createCoreSchema();
111
        }
112 1
        if (!($value instanceof NodeGeneric) && !($value instanceof NodeList)) {
113
            throw new \Exception(sprintf(self::WRONG_VALUE, $identifier, gettype($value)));
114
        } else {
115
            // try {
116 1
            if (!preg_match(Regex::TAG_PARTS, $identifier, $matches)) {
117
                throw new \UnexpectedValueException("Tag '$identifier' is invalid", 1);
118
            }
119 1
            return self::runHandler(
120 1
                $matches['handle'],
121 1
                $matches['tagname'],
122 1
                $value,
123 1
                $parent
124 1
            );
125
            // } catch (\UnexpectedValueException $e) {
126
            //     return new Tagged($identifier, is_null($value) ? null : $value->build($parent));
127
            // } catch (\Throwable $e) {
128
            //     throw new \Exception("Tagged value could not be transformed for tag '$identifier'", 1, $e);;
129
            // }
130
        }
131
    }
132
133 2
    public static function runHandler($handle, $tagname, $value, &$parent = null)
134
    {
135 2
        if (array_key_exists($handle, self::$schemaHandles)) {
136 2
            $schemaName = self::$schemaHandles[$handle];
137 2
            if (array_key_exists($schemaName, self::$schemas)) {
138 2
                $schemaObject = self::$schemas[$schemaName];
139 2
                if (is_object($schemaObject) && is_string($tagname)) {
140 2
                    return $schemaObject->{$tagname}($value, $parent);
141
                }
142
            }
143
        }
144
        throw new \UnexpectedValueException("Error Processing tag '$tagname' : in $handle", 1);
145
    }
146
}
147