TagFactory   A
last analyzed

Complexity

Total Complexity 14

Size/Duplication

Total Lines 122
Duplicated Lines 0 %

Test Coverage

Coverage 83.87%

Importance

Changes 0
Metric Value
wmc 14
eloc 33
dl 0
loc 122
ccs 26
cts 31
cp 0.8387
rs 10
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A registerHandle() 0 6 2
A registerSchema() 0 3 1
A transform() 0 17 5
A createCoreSchema() 0 5 1
A runHandler() 0 12 5
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