Extensión:JsonConfig
La extensión JsonConfig permite a otras extensiones almacenar sus datos de configuración en forma de blob JSON dentro de una página wiki.
Funcionalidades disponibles y patrones de uso
- Puedes usar JsonConfig para almacenar datos de varias maneras:
- en una sola página de configuración, por ejemplo, una serie de ajustes para su extensión en Config:MyExtSettings (
Config
es el espacio de nombres predeterminado asociado con la extensión JsonConfig); - en un conjunto de páginas con estructura similar que residen en su propio espacio de nombres, por ejemplo, direcciones IP de proxies conocidos o esquemas de registros de eventos nombrados «Proxy:Opera» o esquemas nombrados Schema:AccountCreation
- usarlo solo para páginas cuyo título se ajuste a un patrón regex, p. ej. Config:Proxy:Opera or Config:Opera.proxy. Esto evita llenar un wiki con numerosos espacios de nombres, uno por cada modelo de contenido.
- en una sola página de configuración, por ejemplo, una serie de ajustes para su extensión en Config:MyExtSettings (
- Puedes proporcionar una clase de contenido para la validación de datos (más allá del JSON válido) y su normalización.
- Puedes proporcionar una clase de visualización para personalizar la apariencia del HTML.
- Puedes almacenar datos:
- «uno por wiki», «uno por agrupación (clúster)» o incluso por «familia» (estructura diferente de la clave de caché para el memcached compartido);
- en un wiki público o privado y accesible con credenciales;
- en una agrupación separada, y notificar de los cambios de forma remota.
Uso dentro del wiki
Actual
- Conjuntos de datos tabulares de Commons
- Conjunto de datos en mapas de Commons
- Configuraciones de dashboards Dashiki
- ¿Otros?
En el pasado
- Configuraciones de operador de Wikipedia Zero (véase Extension:ZeroBanner)
Instalación
- Descarga y extrae los archivos en un directorio denominado «
JsonConfig
» dentro de la carpetaextensions/
.
Developers and code contributors should install the extension from Git instead, using:cd extensions/
git clone https://gerrit.wikimedia.org/r/mediawiki/extensions/JsonConfig - Añade el siguiente código en la parte final de tu archivo LocalSettings.php :
wfLoadExtension( 'JsonConfig' );
- Configúralo según se requiera.
- Hecho – Navega a Special:Version en el wiki para verificar que la extensión se haya instalado correctamente.
Configuración
$wgJsonConfigs
Esta variable define perfiles para cada tipo de página de configuración.
$wgJsonConfigs
es una matriz asociativa de matrices, teniendo cada una de las cuales cero o más de los siguientes parámetros.
Por defecto, JsonConfig usa una clave en forma de cadena de caracteres como identificador del modelo que este perfil representa, pero en caso de que desees reutilizar el mismo identificador de modelo en más de un perfil, puedes invalidarlo mediante el parámetro model
.
parámetro | tipo | por defecto | descripción |
---|---|---|---|
model | string | (clave en $wgJsonConfigs )
|
Identificador del modelo que usar al crear una página nueva. Si no se proporciona ninguno, la clave de matriz de este perfil se convierte en el identificador del modelo. Si se establece el valor a null , se usará el identificador JsonConfig del módulo predefinido. El identificador del modelo también debe estar en la lista de $wgJsonConfigModels excepto para null o 'JsonConfig' .
|
namespace | int | NS_CONFIG (482) | Espacio de nombres en que residirán estas configuraciones, o 'Config:' por defecto |
nsName | string/false | Para espacios de nombres no predeterminados (es decir, distintos de NS_CONFIG 482), se le asigna un nombre canónico (en inglés). Si más de una matriz $wgJsonConfigs usa el mismo espacio de nombres, fija el nombre una sola vez. Si no se encuentra, se dará una advertencia y el espacio de nombres recibirá automáticamente el nombre «ConfigNNN». En caso de que no se almacene localmente esta configuración, se usará nsName como espacio de nombres remoto sin declaración local. Si deseas compartir espacio de nombres con otras páginas que no sean de contenido JsonConfig, fija este valor a | |
nsTalk | string | nsName+_talk
|
Para espacios de nombres no predeterminados, se asigna a sus páginas de discusión un nombre canónico (en inglés). |
pattern | string | (all) | Expresión regular para coincidir con el título de la página en el espacio de nombres dado. Si está vacío, la configuración se aplicará a todas las páginas del espacio de nombres. Para adoptar el antiguo comportamiento de «subespacios», para isSubspace=true , usa el patrón ^/^name:./ , y para isSubspace=false , usa el patrón /^name$/ .
|
isLocal | bool | true | Si el valor es true , esta configuración no se compartirá por toda la agrupación, sino que cada wiki tendrá una configuración local. Si el valor es false , se pretende que esta configuración se comparta entre múltiples wikis, y para hacer que este wiki específico la almacene en local, fija el campo 'store'.Esta bandera afecta a la clave de caché, de forma que una página de configuración con el mismo nombre será almacenada en memcached si el valor es
false , pero será única por wiki si el valor es true . |
cacheExp | int | 24*60*60 | Duración (en segundos) del almacenamiento del valor en caché en memcached |
cacheKey | string | Si se ha establecido el valor, añade esa cadena a la clave de caché. Usa cacheKey para invalidar los valores anteriores en caché: p. ej. cuando realices un cambio incompatible que modificaría los valores en caché y te preocupa la posibilidad de que necesites revertirlo. Esta clave también se puede usar para permitir que todos los wikis en distintos idiomas pertenecientes a la misma familia compartan el mismo valor en caché a la vez que se almacenan en la misma página pero en wikis diferentes. Por ejemplo, Wikipedia podría usar «wp» y Wikiquote «wq».
| |
flaggedRevs | bool | false | Si el valor es true , se intentará recuperar la última revisión que haya sido verificada mediante la extensión de revisiones marcadas (FlaggedRevs); si es null , se comprobará la revisión marcada, y, si está disponible, se usará. Si es false , se usará siempre la última revisión.
|
remote | array | Un objeto con parámetros que describen cómo acceder a la configuración desde otro wiki. Debe estar presente si no se ha inicializado 'store' y si el valor de isLocal es false .
| |
‑ url | string | Punto de acceso distinto del predeterminado de la API desl que obtener la configuración del wiki remoto sólo para este perfil de configuración. Si no se especifica, se usará el valor de $wgJsonConfigApiUri .
| |
‑ username | string | Si se da, se usará para la autenticación del usuario contra el almacenamiento de configuración remoto. | |
‑ password | string | Véase username .
| |
store | array | Inicializa este valor a true o a una matriz para que que el wiki actual aloje estos datos de configuración. Este valor se rellenará automáticamente si está ausente y el valor de isLocal es true .
| |
‑ cacheNewValue | bool | true | Cómo debe cambiar la caché ante cambios de configuración. Si el valor es false , elimina el valor almacenado en caché forzando a otros wikis a volver a pedirlo. true fija el nuevo valor en la caché. Esto es útil sobre todo si el wiki que almacena esta configuración y los wikis que la consumen comparten la misma caché. Ten en cuenta que, en caso de false , si el wiki consumidor pide el nuevo valor demasiado rápido, podría obtenerlo de una base de datos esclava posiblemente obsoleta.
|
‑ notifyUrl | string | Especifica opcionalmente la URL de la API remota a la que se llamará ante un cambio de la configuración. | |
‑ notifyUsername | string | Nombre de usuario opcional para utilizar con notifyUrl
| |
‑ notifyPassword | string | Contraseña opcional para utilizar con notifyUrl
|
$wgJsonConfigModels
Esta variable define qué clase de contenido personalizada manejará qué identificador de modelo (modelID).
Una misma clase de contenido puede manejar más de un identificador de modelo.
Todas las clases de contenido deben derivarse de la clase JCContent
; si el modelID corresponde a null
, entonces la clase por defecto JCContent
manejará el identificador de modelo.
Ejemplo:
$wgJsonConfigModels['Config.MyExtSettings'] = 'MyExt\MyContentClass';
Si implementas una clase separada para renderizar el HTML, puedes especificar el modelo de configuración como una matriz con la clase adicional view
:
$wgJsonConfigModels['Config.MyExtSettings'] = [
'class' => 'MyExt\MyContentClass',
'view' => 'MyExt\MyContentViewClass', // easier to extend JCDefaultObjContentView or JCDefaultContentView
];
Ejemplos
name
y isSubspace
para personalizar qué páginas pertenecían al modelo de contenido dado. Los dos se han eliminado en la versión 1.0.0, siendo reemplazados por el parámetro pattern
, que acepta una expresión regular. Asegúrate de delimitar tus patrones con los símbolos ^ y $, y añade barras oblicuas (estilo PHP)
Hola mundo
El caso más simple es una sola página de configuración sin validación alguna almacenada de forma local en cada wiki. Simplemente añade estas declaraciones a LocalSettings.php
// Content model is 'JsonConfig.MySettings'
// Model class is set to NULL to allow non-validated data
$wgJsonConfigModels['JsonConfig.MySettings'] = null;
$wgJsonConfigs['JsonConfig.MySettings'] = array(
'pattern' => '/^MySettings$/', // Page name in Config namespace
);
Lo anterior habilita el espacio de nombres «Config» en el wiki local, pero no permite crear en ese espacio de nombres más que la página «Config:MySettings». Puedes almacenar en la página datos en forma de JSON bien formado.
Para leer los datos de MySettings en PHP, utiliza un objeto TitleValue
para acceder a la página, y luego solicita su contenido:
use JsonConfig\JCSingleton;
$tv = new TitleValue( NS_CONFIG, 'MySettings' ); // DB Key
$content = JCSingleton::GetContent( $tv );
if ( $content->isValid() ) {
$data = $content->getData();
...
}
Implementar plantillas Wikimedia
Algunas plantillas de proyectos Wikimedia (p. ej., Template:TNT) requieren que JsonConfig tenga soporte para el espacio de nombres Data en Commons para mw.ext.data.get
. Puedes usar la siguiente configuración para implementar ese caso de uso.
wfLoadExtension( 'JsonConfig' );
$wgJsonConfigEnableLuaSupport = true; // required to use JsonConfig in Lua
$wgJsonConfigModels['Tabular.JsonConfig'] = 'JsonConfig\JCTabularContent';
$wgJsonConfigs['Tabular.JsonConfig'] = [
'namespace' => 486,
'nsName' => 'Data',
// page name must end in ".tab", and contain at least one symbol
'pattern' => '/.\.tab$/',
'license' => 'CC0-1.0',
'isLocal' => false,
];
$wgJsonConfigModels['Map.JsonConfig'] = 'JsonConfig\JCMapDataContent';
$wgJsonConfigs['Map.JsonConfig'] = [
'namespace' => 486,
'nsName' => 'Data',
// page name must end in ".map", and contain at least one symbol
'pattern' => '/.\.map$/',
'license' => 'CC0-1.0',
'isLocal' => false,
];
$wgJsonConfigInterwikiPrefix = "commons";
$wgJsonConfigs['Tabular.JsonConfig']['remote'] = [
'url' => 'https://commons.wikimedia.org/w/api.php'
];
$wgJsonConfigs['Map.JsonConfig']['remote'] = [
'url' => 'https://commons.wikimedia.org/w/api.php'
];
Configuraciones múltiples compartidas en una agrupación (clúster)
Digamos que decidimor almacenar las direcciones IP de los proxies de confianza como páginas «Config:Proxy:Ejemplo» en Meta-Wiki y compartir estos datos con la agrupación.
// All wikis must have this configuration:
$wgJsonConfigs['JsonConfig.Proxy'] = [
'pattern' => '/^Proxy\:./', // require at least one letter after the ':'
'isLocal' => false,
];
// The LocalSettings.php for all wikis except Meta-Wiki will set this URL to Meta-Wiki's API endpoint:
$wgJsonConfigs['JsonConfig.Proxy']['remote'] = 'http://meta.wikimedia.org/w/api.php';
// LocalSettings.php for Meta-Wiki will indicate that the data should be stored there
$wgJsonConfigs['JsonConfig.Proxy']['store'] = true;
Si en vez de esto prefieres dedicar un espacio de nombres separado a los proxies, los parámetros cambiarán a:
$wgJsonConfigs['JsonConfig.Proxy'] = [
'namespace' => NNN, // NNN is the number you would reserve for Proxy namespace
'nsName' => 'Proxy', // Canonical namespace name
];
Validación
La mayoría de las veces se desea también una clase de contenido personalizada con su propia validación.
Las páginas JSON se manejan mediante las clases de contenido que derivan de JCContent
.
La clase de contenido es responsable de analizar y validar el texto en crudo.
JCContent
no hace ninguna validación más allá del análisis del JSON, pero puedes derivar de ella y redefinir JCContent::validate()
.
Aún mejor, puedes derivar la clase JCObjContent
que proporciona una serie de primitivas de validación y redefinir solamente JCObjContent::validateContent()
.
// This should be done on all wikis, including Meta-Wiki
$wgJsonConfigModels['JsonConfig.Proxy'] = 'ProxyExt\ProxyContent';
Para el propósito de esta documentación, asumamos que la página de configuración del proxy que describe los servidores Opera Mini tiene esta formato:
{
"enabled": true,
"comment": "See http://... for updates",
"ips": [
'37.228.104.0/21',
...
]
}
He aquí la clase de contenido para validar esos datos.
use JsonConfig\JCObjContent;
use JsonConfig\JCValidators;
class ProxyContent extends JCObjContent {
/**
* Derived classes must implement this method to perform custom validation
* using the check(...) calls
*/
public function validateContent() {
// 'enabled' must be a boolean, true by default.
// JCValidators::* already handle localized error messages
$this->testOptional( 'enabled', true, JCValidators::isBool() );
// an optional field 'comment' of type string
$this->testOptional( 'comment', '', JCValidators::isString() );
// 'ips' must be a list of valid CIDR ranges
// field is not optional when default value would not pass validation
$this->test( 'ips', self::getIpValidator() );
}
private static function getIpValidator() {
// JCValue $value is a value of the field being checked wrapped with the status information.
// $v->getValue() actual value being examined
// $v->isMissing() if the value is not present in the data
// $v->defaultUsed() if the value did not exist and a default was supplied
// array $path the location of this field in the hierarchy - each value is either string or an int
// JCObjContent $self - this object, useful to get access to other fields via $self->getField()
// You may modify the value stored inside, set additional flags, or report an error
// using the $v->error( $key, $path, ... ) function
return function ( JCValue $value, array $path, JCObjContent $self ) {
$isErr = false;
$v = $value->getValue();
if ( is_string( $v ) ) {
// user supplied a single string, treat as an non-assoc array
$v = array( $v );
} else {
// ensure that $v is an non-assoc array, and all of its values are strings
$isErr = !JCUtils::isList( $v ) || !JCUtils::allValuesAreStrings( $v );
}
if ( !$isErr ) {
// @todo: do the rest of the IP validation and set $isErr to true on failure
}
// Error message might be in this form:
// "Parameter \"$1\" must be an array of valid non-restricted (no private networks) CIDR IP blocks"
if ( $isErr ) {
$value->error( 'my-proxyconfig-err-ips', $path );
} else {
$value->setValue( $v );
}
};
}
}
Personalizar el comportamiento en el wiki de almacenamiento
Puede que también desees personalizar la visualización y creación de páginas en el wiki de almacenamiento (Meta-Wiki en el ejemplo anterior).
Hay dos formas de hacerlo: dentro de tu clase derivada de JCContent
o mediante una clase separada de «vista» derivada de JCContentView
.
El segundo enfoque es preferible, ya que separa claramente la arquitectura y la clase de vista solo tiene necesidad de existir en el wiki de almacenamiento (p. ej. Meta-Wiki) y no en todos los wikis que usan los datos.
Para redefinir el valor por defecto en una clase derivada de JCContent
, redefine el constructor y establece el valor de $text
con el nuevo valor por defecto si se inicializó con el valor NULL antes de pasarlo al constructor del padre.
Para redefinir la generación del HTML, redefine JCContent::getHtml()
.
Al seguir el método recomendado, crea una clase de vista que derive de JCContentView
o una clase JCDefaultContentView
con más funcionalidades.
En el caso de JCContentView
, deberás implementar valueToHtml()
y getDefault()
.
Por defecto, la vista está implementada por la clase JCDefaultContentView
, que también se puede utilizar como una base personalizable si solamente necesitas realizar ajustes menores en lo que se refiere a su apariencia.
// Los cambios en la definición del modelo según lo anterior deben hacerse en todos los wikis, incluido META
$wgJsonConfigModels['JsonConfig.Proxy'] = [ 'class' => 'ProxyExt\ProxyContent' ];
// Añade la clase de la vista - se debe hacer sólo en el wiki de almacenamiento (p. ej. META)
$wgJsonConfigModels['JsonConfig.Proxy']['view'] = 'ProxyExt\ProxyView';
class ProxyView extends JsonConfig\JCDefaultObjContentView {
public function getDefault( $modelId ) {
return <<<JSON
{
"comment": "See http://... for updates",
"ips": [
"N.N.N.N/NN",...
]
}
JSON;
}
}
Buenas prácticas
- Las extensiones que utilicen JsonConfig deberían añadir sus configuraciones a
$wgJsonConfigs
y$wgJsonConfigModels
en el archivo principal de extensión. - Si compartes datos de configuración entre varios wikis, documenta el nombre de la clave utilizada en
$wgJsonConfigs[]
e inicializa la sección 'store'/'remote' enLocalSettings.php
. Esto es mejor que introducir una serie de variables globales que duplican la funcionalidad de la configuración. Véase por ejemplo la configuración de Wikimedia de la extensión Graph entre múltiples wikis (aunque esto utiliza una configuración multiwiki compleja en lugar de simples variables de configuración).
Estado
Funcionalidades implementadas
- El análisis sintáctico JSON convierte el texto JSON en una matriz o un objeto
- La visualización muestra el JSON en forma de tabla intuitiva en lugar de en forma de código, con algunos resaltados suplementarios. Por ejemplo, si no se proporciona un valor sino que se utiliza el valor por defecto, se muestra en gris, y cuando el valor coincide con el valor por defecto, se muestra en morado. Por ejemplo, véase esto y esto.
- El editor de código simplifica la edición de JSON
- La validación personalizada realiza comprobaciones complejas tales como verificar que el valor se encuentra en el formato adecuado o que un identificador de usuario existe.
- El almacenamiento en caché MemCached almacena blobs JSON en MemCached (caché de memoria) con claves y políticas de expiración personalizadas, y las resetea al guardar.
- El soporte de revisiones marcadas permite que se marquen las configuraciones como «revisadas» antes de entrar en producción
- La localización de los elementos de interfaz más básicos se ha llevado a cabo en muchos idiomas, y reduciría el trabajo de traducción si la mayoría de los mensajes comunes se gestionara una sola vez en un sitio.
Funcionalidades aún sin implementar, pero bienvenidas
Estas funcionalidades serían deseables para más de un tipo de configuración:
- Validador de esquemas - valida el JSON Schema, teniendo en cuenta que la mayoría de las extensiones no necesitan reglas de complejas de validación, con la posibilidad de combinar el esquema con una validación suplementaria.
- Editor personalizado - el equipo cero ha estado pensando en implementar un editor más complejo, posiblemente basado en el esquema JSON.
- Soporte de consultas a la API - permite que se devuelvan páginas de configuración como resultados regulares de la API en todos los formatos - json/xml/... en lugar de como blobs de texto:
api.php ? action=query & titles=Config:Proxy:Opera & prop=jsonconfig
- Localización - sería deseable poder mostrar descripciones localizadas para cada clave de configuración
Acceso externo
Los datos de configuración almacenados a menudo pueden ser requeridos por algún agente externo como JavaScript, un bot u otros programas.
JavaScript podría utilizar JSONP para acceder a los datos requeridos mediante una llamada estándar a la API action=query&rvprop=content
, o bien podríamos desarrollar un servicio de reenvío si CORS no está disponible.
Los autores de extensiones pueden optar por añadir sus propios módulos de API para proporcionar información específica del dominio.
Por último, el parámetro rvprop=jcddata
de consulta de la API podría devolver datos JSON como parte del resultado de la API en lugar del blob de texto que rvprop=content
devolvería normalmente.
// ¡NO IMPLEMENTADO! Usa la API regular action=query hasta que decidamos cómo hacerlo bien
var req = {
format: 'json', action: 'query',
titles: 'Proxy:Opera',
prop: 'revisions', rvprop: 'jcdcontent', indexpageids: '',
};
$.ajax({
url: '//meta.wikipedia.org/w/api.php',
data: req, cache: true, dataType: 'jsonp',
success: function(result) { /* maneja errores y advertencias, procesa el contenido */ }
});
Véase también
Esta extensión está siendo usada en uno o más proyectos de Wikimedia. Esto significa probablemente que la extensión es estable y funciona lo suficientemente bien como para ser usada en sitios con gran cantidad de visitas. Puedes buscar el nombre de esta extensión en los archivos CommonSettings.php e InitialiseSettings.php de Wikimedia para ver dónde se instala. Encontrarás la lista completa de extensiones instaladas en un wiki en particular en la página Special:Version del wiki. |
Esta extensión está incluida en los siguientes anfitriones/granjas wiki y/o paquetes: No se trata de una lista oficial. Algunas granjas/hosts wiki y/o paquetes pueden tener disponible esta extensión aunque no estén listados aquí. Siempre compruébelo con su anfitrión o granja wiki para confirmarlo. |
- Stable extensions/es
- ContentHandler extensions/es
- Personalization extensions/es
- GPL licensed extensions/es
- Extensions in Wikimedia version control/es
- AlternateEdit extensions/es
- ApiMain::moduleManager extensions/es
- ArticleDeleteComplete extensions/es
- ArticleUndelete extensions/es
- BeforePageDisplay extensions/es
- CanonicalNamespaces extensions/es
- CodeEditorGetPageLanguage extensions/es
- ContentHandlerDefaultModelFor extensions/es
- ContentHandlerForModelID extensions/es
- EditFilterMergedContent extensions/es
- EditPage::showEditForm:initial extensions/es
- EditPageCopyrightWarning extensions/es
- GetContentModels extensions/es
- LinksUpdateComplete extensions/es
- LoadExtensionSchemaUpdates extensions/es
- MovePageIsValidMove extensions/es
- PageMoveComplete extensions/es
- PageSaveComplete extensions/es
- ScribuntoExternalLibraries extensions/es
- SkinCopyrightFooterMessage extensions/es
- TitleGetEditNotices extensions/es
- GetUserPermissionsErrors extensions/es
- All extensions/es
- Extensions used on Wikimedia/es
- Extensions included in Miraheze/es
- Extensions included in MyWikis/es
- Extensions included in WikiForge/es