Chris@18
|
1 <?php
|
Chris@18
|
2
|
Chris@18
|
3 namespace Drupal\jsonapi;
|
Chris@18
|
4
|
Chris@18
|
5 /**
|
Chris@18
|
6 * Defines constants used for compliance with the JSON:API specification.
|
Chris@18
|
7 *
|
Chris@18
|
8 * @internal JSON:API maintains no PHP API since its API is the HTTP API. This
|
Chris@18
|
9 * class may change at any time and this will break any dependencies on it.
|
Chris@18
|
10 *
|
Chris@18
|
11 * @see https://www.drupal.org/project/jsonapi/issues/3032787
|
Chris@18
|
12 * @see jsonapi.api.php
|
Chris@18
|
13 *
|
Chris@18
|
14 * @see http://jsonapi.org/format
|
Chris@18
|
15 */
|
Chris@18
|
16 class JsonApiSpec {
|
Chris@18
|
17
|
Chris@18
|
18 /**
|
Chris@18
|
19 * The minimum supported specification version.
|
Chris@18
|
20 *
|
Chris@18
|
21 * @see http://jsonapi.org/format/#document-jsonapi-object
|
Chris@18
|
22 */
|
Chris@18
|
23 const SUPPORTED_SPECIFICATION_VERSION = '1.0';
|
Chris@18
|
24
|
Chris@18
|
25 /**
|
Chris@18
|
26 * The URI of the supported specification document.
|
Chris@18
|
27 */
|
Chris@18
|
28 const SUPPORTED_SPECIFICATION_PERMALINK = 'http://jsonapi.org/format/1.0/';
|
Chris@18
|
29
|
Chris@18
|
30 /**
|
Chris@18
|
31 * Member name: globally allowed characters.
|
Chris@18
|
32 *
|
Chris@18
|
33 * U+0080 and above (non-ASCII Unicode characters) are allowed, but are not
|
Chris@18
|
34 * URL-safe. It is RECOMMENDED to not use them.
|
Chris@18
|
35 *
|
Chris@18
|
36 * A character class, for use in regular expressions.
|
Chris@18
|
37 *
|
Chris@18
|
38 * @see http://jsonapi.org/format/#document-member-names-allowed-characters
|
Chris@18
|
39 * @see http://php.net/manual/en/regexp.reference.character-classes.php
|
Chris@18
|
40 */
|
Chris@18
|
41 const MEMBER_NAME_GLOBALLY_ALLOWED_CHARACTER_CLASS = '[a-zA-Z0-9\x{80}-\x{10FFFF}]';
|
Chris@18
|
42
|
Chris@18
|
43 /**
|
Chris@18
|
44 * Member name: allowed characters except as the first or last character.
|
Chris@18
|
45 *
|
Chris@18
|
46 * Space (U+0020) is allowed, but is not URL-safe. It is RECOMMENDED to not
|
Chris@18
|
47 * use it.
|
Chris@18
|
48 *
|
Chris@18
|
49 * A character class, for use in regular expressions.
|
Chris@18
|
50 *
|
Chris@18
|
51 * @see http://jsonapi.org/format/#document-member-names-allowed-characters
|
Chris@18
|
52 * @see http://php.net/manual/en/regexp.reference.character-classes.php
|
Chris@18
|
53 */
|
Chris@18
|
54 const MEMBER_NAME_INNER_ALLOWED_CHARACTERS = "[a-zA-Z0-9\x{80}-\x{10FFFF}\-_ ]";
|
Chris@18
|
55
|
Chris@18
|
56 /**
|
Chris@18
|
57 * Checks whether the given member name is valid.
|
Chris@18
|
58 *
|
Chris@18
|
59 * Requirements:
|
Chris@18
|
60 * - it MUST contain at least one character.
|
Chris@18
|
61 * - it MUST contain only the allowed characters
|
Chris@18
|
62 * - it MUST start and end with a "globally allowed character"
|
Chris@18
|
63 *
|
Chris@18
|
64 * @param string $member_name
|
Chris@18
|
65 * A member name to validate.
|
Chris@18
|
66 *
|
Chris@18
|
67 * @return bool
|
Chris@18
|
68 * Whether the given member name is in compliance with the JSON:API
|
Chris@18
|
69 * specification.
|
Chris@18
|
70 *
|
Chris@18
|
71 * @see http://jsonapi.org/format/#document-member-names
|
Chris@18
|
72 */
|
Chris@18
|
73 public static function isValidMemberName($member_name) {
|
Chris@18
|
74 // @todo When D8 requires PHP >=5.6, move to a MEMBER_NAME_REGEXP constant.
|
Chris@18
|
75 static $regexp;
|
Chris@18
|
76 // @codingStandardsIgnoreStart
|
Chris@18
|
77 if (!isset($regexp)) {
|
Chris@18
|
78 $regexp = '/^' .
|
Chris@18
|
79 // First character must be "globally allowed". Length must be >=1.
|
Chris@18
|
80 self::MEMBER_NAME_GLOBALLY_ALLOWED_CHARACTER_CLASS . '{1}' .
|
Chris@18
|
81 '(' .
|
Chris@18
|
82 // As many non-globally allowed characters as desired.
|
Chris@18
|
83 self::MEMBER_NAME_INNER_ALLOWED_CHARACTERS . '*' .
|
Chris@18
|
84 // If length > 1, then it must end in a "globally allowed" character.
|
Chris@18
|
85 self::MEMBER_NAME_GLOBALLY_ALLOWED_CHARACTER_CLASS . '{1}' .
|
Chris@18
|
86 // >1 characters is optional.
|
Chris@18
|
87 ')?' .
|
Chris@18
|
88 '$/u';
|
Chris@18
|
89 }
|
Chris@18
|
90 // @codingStandardsIgnoreEnd
|
Chris@18
|
91
|
Chris@18
|
92 return preg_match($regexp, $member_name) === 1;
|
Chris@18
|
93 }
|
Chris@18
|
94
|
Chris@18
|
95 /**
|
Chris@18
|
96 * The reserved (official) query parameters.
|
Chris@18
|
97 *
|
Chris@18
|
98 * @todo When D8 requires PHP >= 5.6, convert to an array.
|
Chris@18
|
99 */
|
Chris@18
|
100 const RESERVED_QUERY_PARAMETERS = 'filter|sort|page|fields|include';
|
Chris@18
|
101
|
Chris@18
|
102 /**
|
Chris@18
|
103 * The query parameter for providing a version (revision) value.
|
Chris@18
|
104 *
|
Chris@18
|
105 * @var string
|
Chris@18
|
106 */
|
Chris@18
|
107 const VERSION_QUERY_PARAMETER = 'resourceVersion';
|
Chris@18
|
108
|
Chris@18
|
109 /**
|
Chris@18
|
110 * Gets the reserved (official) JSON:API query parameters.
|
Chris@18
|
111 *
|
Chris@18
|
112 * @return string[]
|
Chris@18
|
113 * Gets the query parameters reserved by the specification.
|
Chris@18
|
114 */
|
Chris@18
|
115 public static function getReservedQueryParameters() {
|
Chris@18
|
116 return explode('|', static::RESERVED_QUERY_PARAMETERS);
|
Chris@18
|
117 }
|
Chris@18
|
118
|
Chris@18
|
119 /**
|
Chris@18
|
120 * Checks whether the given custom query parameter name is valid.
|
Chris@18
|
121 *
|
Chris@18
|
122 * A custom query parameter name must be a valid member name, with one
|
Chris@18
|
123 * additional requirement: it MUST contain at least one non a-z character.
|
Chris@18
|
124 *
|
Chris@18
|
125 * Requirements:
|
Chris@18
|
126 * - it MUST contain at least one character.
|
Chris@18
|
127 * - it MUST contain only the allowed characters
|
Chris@18
|
128 * - it MUST start and end with a "globally allowed character"
|
Chris@18
|
129 * - it MUST contain at least none a-z (U+0061 to U+007A) character
|
Chris@18
|
130 *
|
Chris@18
|
131 * It is RECOMMENDED that a hyphen (U+002D), underscore (U+005F) or capital
|
Chris@18
|
132 * letter is used (i.e. camelCasing).
|
Chris@18
|
133 *
|
Chris@18
|
134 * @param string $custom_query_parameter_name
|
Chris@18
|
135 * A custom query parameter name to validate.
|
Chris@18
|
136 *
|
Chris@18
|
137 * @return bool
|
Chris@18
|
138 * Whether the given query parameter is in compliane with the JSON:API
|
Chris@18
|
139 * specification.
|
Chris@18
|
140 *
|
Chris@18
|
141 * @see http://jsonapi.org/format/#query-parameters
|
Chris@18
|
142 */
|
Chris@18
|
143 public static function isValidCustomQueryParameter($custom_query_parameter_name) {
|
Chris@18
|
144 return static::isValidMemberName($custom_query_parameter_name) && preg_match('/[^a-z]/u', $custom_query_parameter_name) === 1;
|
Chris@18
|
145 }
|
Chris@18
|
146
|
Chris@18
|
147 }
|