Page Menu
Home
WickedGov Phorge
Search
Configure Global Search
Log In
Files
F5959213
JsonSchemaTrait.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
6 KB
Referenced Files
None
Subscribers
None
JsonSchemaTrait.php
View Options
<?php
namespace
MediaWiki\Settings\Source
;
use
InvalidArgumentException
;
/**
* Trait for dealing with JSON Schema structures and types.
*
* @since 1.39
*/
trait
JsonSchemaTrait
{
/**
* Converts a JSON Schema type to a PHPDoc type.
*
* @param string|string[] $jsonSchemaType A JSON Schema type
*
* @return string A PHPDoc type
*/
private
static
function
jsonToPhpDoc
(
$jsonSchemaType
)
{
static
$phpTypes
=
[
'array'
=>
'array'
,
'object'
=>
'array'
,
// could be optional
'number'
=>
'float'
,
'double'
=>
'float'
,
// for good measure
'boolean'
=>
'bool'
,
'integer'
=>
'int'
,
];
if
(
$jsonSchemaType
===
null
)
{
throw
new
InvalidArgumentException
(
'The type name cannot be null! Use "null" instead.'
);
}
$nullable
=
false
;
if
(
is_array
(
$jsonSchemaType
)
)
{
$nullIndex
=
array_search
(
'null'
,
$jsonSchemaType
);
if
(
$nullIndex
!==
false
)
{
$nullable
=
true
;
unset
(
$jsonSchemaType
[
$nullIndex
]
);
}
$jsonSchemaType
=
array_map
(
[
self
::
class
,
'jsonToPhpDoc'
],
$jsonSchemaType
);
$type
=
implode
(
'|'
,
$jsonSchemaType
);
}
else
{
$type
=
$phpTypes
[
strtolower
(
$jsonSchemaType
)
]
??
$jsonSchemaType
;
}
if
(
$nullable
)
{
$type
=
"?$type"
;
}
return
$type
;
}
/**
* @param string|string[] $phpDocType The PHPDoc type
*
* @return string|string[] A JSON Schema type
*/
private
static
function
phpDocToJson
(
$phpDocType
)
{
static
$jsonTypes
=
[
'list'
=>
'array'
,
'dict'
=>
'object'
,
'map'
=>
'object'
,
'stdclass'
=>
'object'
,
'int'
=>
'integer'
,
'float'
=>
'number'
,
'bool'
=>
'boolean'
,
'false'
=>
'boolean'
,
];
if
(
$phpDocType
===
null
)
{
throw
new
InvalidArgumentException
(
'The type name cannot be null! Use "null" instead.'
);
}
if
(
is_array
(
$phpDocType
)
)
{
$types
=
$phpDocType
;
}
else
{
$types
=
explode
(
'|'
,
trim
(
$phpDocType
)
);
}
$nullable
=
false
;
foreach
(
$types
as
$i
=>
$t
)
{
if
(
str_starts_with
(
$t
,
'?'
)
)
{
$nullable
=
true
;
$t
=
substr
(
$t
,
1
);
}
$types
[
$i
]
=
$jsonTypes
[
strtolower
(
$t
)
]
??
$t
;
}
if
(
$nullable
)
{
$types
[]
=
'null'
;
}
$types
=
array_unique
(
$types
);
if
(
count
(
$types
)
===
1
)
{
return
reset
(
$types
);
}
return
$types
;
}
/**
* Applies phpDocToJson() to type declarations in a JSON schema.
*
* @param array $schema JSON Schema structure with PHPDoc types
* @param array &$defs List of definitions (JSON schemas) referenced in the schema
* @param string $source An identifier for the source schema being reflected, used
* for error descriptions.
* @param string $propertyName The name of the property the schema belongs to, used for error descriptions.
* @return array JSON Schema structure using only proper JSON types
*/
private
static
function
normalizeJsonSchema
(
array
$schema
,
array
&
$defs
,
string
$source
,
string
$propertyName
,
bool
$inlineReferences
=
false
):
array
{
$traversedReferences
=
[];
return
self
::
doNormalizeJsonSchema
(
$schema
,
$defs
,
$source
,
$propertyName
,
$inlineReferences
,
$traversedReferences
);
}
/**
* Recursively applies phpDocToJson() to type declarations in a JSON schema.
*
* @param array $schema JSON Schema structure with PHPDoc types
* @param array &$defs List of definitions (JSON schemas) referenced in the schema
* @param string $source An identifier for the source schema being reflected, used
* for error descriptions.
* @param string $propertyName The name of the property the schema belongs to, used for error descriptions.
* @param bool $inlineReferences Whether references in the schema should be inlined or not.
* @param array $traversedReferences An accumulator for the resolved references within a schema normalization,
* used for cycle detection.
* @return array JSON Schema structure using only proper JSON types
*/
private
static
function
doNormalizeJsonSchema
(
array
$schema
,
array
&
$defs
,
string
$source
,
string
$propertyName
,
bool
$inlineReferences
,
array
$traversedReferences
):
array
{
if
(
isset
(
$schema
[
'type'
]
)
)
{
// Support PHP Doc style types, for convenience.
$schema
[
'type'
]
=
self
::
phpDocToJson
(
$schema
[
'type'
]
);
}
if
(
isset
(
$schema
[
'additionalProperties'
]
)
&&
is_array
(
$schema
[
'additionalProperties'
]
)
)
{
$schema
[
'additionalProperties'
]
=
self
::
doNormalizeJsonSchema
(
$schema
[
'additionalProperties'
],
$defs
,
$source
,
$propertyName
,
$inlineReferences
,
$traversedReferences
);
}
if
(
isset
(
$schema
[
'items'
]
)
&&
is_array
(
$schema
[
'items'
]
)
)
{
$schema
[
'items'
]
=
self
::
doNormalizeJsonSchema
(
$schema
[
'items'
],
$defs
,
$source
,
$propertyName
,
$inlineReferences
,
$traversedReferences
);
}
if
(
isset
(
$schema
[
'properties'
]
)
&&
is_array
(
$schema
[
'properties'
]
)
)
{
foreach
(
$schema
[
'properties'
]
as
$name
=>
$propSchema
)
{
$schema
[
'properties'
][
$name
]
=
self
::
doNormalizeJsonSchema
(
$propSchema
,
$defs
,
$source
,
$propertyName
,
$inlineReferences
,
$traversedReferences
);
}
}
if
(
isset
(
$schema
[
'$ref'
]
)
)
{
$definitionName
=
JsonSchemaReferenceResolver
::
getDefinitionName
(
$schema
[
'$ref'
]
);
if
(
array_key_exists
(
$definitionName
,
$traversedReferences
)
)
{
throw
new
RefLoopException
(
"Found a loop while resolving reference $definitionName in $propertyName."
.
" Root schema location: $source"
);
}
$def
=
JsonSchemaReferenceResolver
::
resolveRef
(
$schema
[
'$ref'
],
$source
);
if
(
$def
)
{
if
(
!
isset
(
$defs
[
$definitionName
]
)
)
{
$traversedReferences
[
$definitionName
]
=
true
;
$normalizedDefinition
=
self
::
doNormalizeJsonSchema
(
$def
,
$defs
,
$source
,
$propertyName
,
$inlineReferences
,
$traversedReferences
);
if
(
!
$inlineReferences
)
{
$defs
[
$definitionName
]
=
$normalizedDefinition
;
}
}
else
{
$normalizedDefinition
=
$defs
[
$definitionName
];
}
// Normalize reference after resolving it since JsonSchemaReferenceResolver expects
// the $ref to be an array with: [ "class" => "Some\\Class", "field" => "someField" ]
if
(
$inlineReferences
)
{
$schema
=
$normalizedDefinition
;
}
else
{
$schema
[
'$ref'
]
=
JsonSchemaReferenceResolver
::
normalizeRef
(
$schema
[
'$ref'
]
);
}
}
}
return
$schema
;
}
/**
* Returns the default value from the given schema structure.
* If the schema defines properties, the default value of each
* property is determined recursively, and the collected into a
* the top level default, which in that case will be a map
* (that is, a JSON object).
*
* @param array $schema
* @return mixed The default specified by $schema, or null if no default
* is defined.
*/
private
static
function
getDefaultFromJsonSchema
(
array
$schema
)
{
$default
=
$schema
[
'default'
]
??
null
;
foreach
(
$schema
[
'properties'
]
??
[]
as
$name
=>
$sch
)
{
$def
=
self
::
getDefaultFromJsonSchema
(
$sch
);
$default
[
$name
]
=
$def
;
}
return
$default
;
}
}
File Metadata
Details
Attached
Mime Type
text/x-php
Expires
Sat, Oct 3, 06:17 (2 w, 4 d ago)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
cc/8f/2960b4b877414c6e2e23eb97e7d2
Default Alt Text
JsonSchemaTrait.php (6 KB)
Attached To
Mode
rMWPROD MediaWiki Production
Attached
Detach File
Event Timeline
Log In to Comment