Écrire une mise à niveau de plugin
De temps en temps, il arrive un moment où un plugin doit modifier le contenu ou la structure des données qu’il a stockées soit dans la base de données, soit dans le répertoire des données.
La raison de ceci pourrait être que la structure des données doit être convertie en une structure plus efficace ou plus flexible. Ou peut-être en raison d’un bogue les éléments de données ont été enregistrés d’une manière non valide, et ils doivent être convertis dans le format correct.
Migrations and convertions like this may take a long time if there is a lot of
data to be processed. This is why Elgg provides the Elgg\Upgrade\AsynchronousUpgrade
class
that can be used for implementing long-running upgrades.
Déclarer la mise à niveau d’un plugin
Plugin can communicate the need for an upgrade under the upgrades
key in
elgg-plugin.php
file. Each value of the array must be the fully qualified
name of an upgrade class that extends the Elgg\Upgrade\AsynchronousUpgrade
class.
Exemple tiré du fichier mod/blog/elgg-plugin.php
:
return [
'upgrades' => [
Blog\Upgrades\AccessLevelFix::class,
Blog\Upgrades\DraftStatusUpgrade::class,
]
];
- Les noms de classe dans l’exemple se réfèrent aux classes :
mod/blog/classes/Blog/Upgrades/AccessLevelFix
mod/blog/classes/Blog/Upgrades/DraftStatusUpgrade
Note
Les classes de mise à niveau du noyau Elgg peuvent être déclarées dans engine/lib/upgrades/async-upgrades.php
.
La classe de mise à niveau
A class extending the Elgg\Upgrade\AsynchronousUpgrade
class has a lot of freedom
on how it wants to handle the actual processing of the data. It must however
declare some constant variables and also take care of marking whether each
processed item was upgraded successfully or not.
La structure de base de la classe est la suivante :
<?php
namespace Blog\Upgrades;
use Elgg\Upgrade\AsynchronousUpgrade;
use Elgg\Upgrade\Result;
/**
* Fixes invalid blog access values
*/
class AccessLevelFix extends AsynchronousUpgrade {
/**
* Version of the upgrade
*
* @return int
*/
public function getVersion() {
return 2016120300;
}
/**
* Should the run() method receive an offset representing all processed items?
*
* @return bool
*/
public function needsIncrementOffset() {
return true;
}
/**
* Should this upgrade be skipped?
*
* @return bool
*/
public function shouldBeSkipped() {
return false;
}
/**
* The total number of items to process in the upgrade
*
* @return int
*/
public function countItems() {
// return count of all blogs
}
/**
* Runs upgrade on a single batch of items
*
* @param Result $result Result of the batch (this must be returned)
* @param int $offset Number to skip when processing
*
* @return Result Instance of \Elgg\Upgrade\Result
*/
public function run(Result $result, $offset) {
// fix 50 blogs skipping the first $offset
}
}
Avertissement
Ne présumez pas quand votre classe sera instanciée ou quand/combien de fois ses méthodes publiques seront appelées.
Méthodes de la classe
getVersion()
Cela doit renvoyer un entier représentant la date à laquelle la mise à niveau a été ajoutée. La valeur se compose de huit chiffres au format yyyymmdnn
où:
yyyy
représente l’année
mm
représente le mois (avec le zéro initial)
dd
représente le jour (avec le zéro initial)
nn
est un numéro d’incrément (à partir de00
) qui est utilisé au cas où deux mises à niveau distinctes auraient été ajoutées au cours de la même journée
shouldBeSkipped()
Cela devrait renvoyer false
à moins que la mise à niveau ne soit pas nécessaire.
Avertissement
Si true
est renvoyé, la mise à niveau ne peut pas être exécutée plus tard.
needsIncrementOffset()
Si true
, votre méthode run()
recevra comme $offset
le nombre d’éléments déjà traités. Ceci est utile si vous ne modifiez que des données et que vous devez utiliser le $offset
dans une fonction comme elgg_get_entities()
pour savoir combien d’éléments ont déjà été traités.
Si false
, votre méthode run()
recevra comme $offset
le nombre total d’échecs. false
doit être utilisé si votre processus supprime ou déplace des données en dehors du processus. Par exemple, si vous supprimez 50 objets sur chaque run()
, vous n’avez pas vraiment besoin de $offset
.
countItems()
Récupère le nombre total d’éléments à traiter pendant la mise à niveau. Si ce nombre est inconnu, Batch::UNKNOWN_COUNT
peut être retourné, mais run()
doit alors marquer manuellement la mise à niveau terminée.
run()
Cette fonction doit effectuer une partie de la mise à niveau effective. Et en fonction de la durée nécessaire, elle peut être appelée plusieurs fois au cours d’une seule demande.
Elle reçoit deux arguments :
$result
: Une instance de l’objetElgg\Upgrade\Result
$offset
: Le décalage à partir duquel la prochaine portion de mise à niveau doit commencer (ou le nombre total de défaillances)
Pour chaque élément que la méthode traite, elle doit appeler selon les cas :
$result->addSuccesses()
: Si l’élément a bien été mis à niveau
$result->addFailures()
: Si l’élément n’a pas pu être mis à niveau
Les deux méthodes ont par défaut un seul élément, mais vous pouvez éventuellement passer le nombre d’éléments.
En outre, elle peut définir autant de messages d’erreur que nécessaire dans le cas où quelque chose ne va pas :
$result->addError("Le message d'erreur est indiqué ici")
Si countItems()
renvoie Batch::UNKNOWN_COUNT
, alors à un moment donné run()
doit appeler $result->markComplete()
pour terminer la mise à niveau.
Dans la plupart des cas, votre méthode run()
voudra passer le paramètre $offset
à l’une des fonctions elgg_get_entities()
:
/**
* Process blog posts
*
* @param Result $result The batch result (will be modified and returned)
* @param int $offset Starting point of the batch
* @return Result Instance of \Elgg\Upgrade\Result;
*/
public function run(Result $result, $offset) {
$blogs = elgg_get_entitites([
'type' => 'object'
'subtype' => 'blog'
'offset' => $offset,
]);
foreach ($blogs as $blog) {
if ($this->fixBlogPost($blog)) {
$result->addSuccesses();
} else {
$result->addFailures();
$result->addError("Failed to fix the blog {$blog->guid}.");
}
}
return $result;
}
getUpgrade()
Use this function to get the related ElggUpgrade
entity that is related to this upgrade.
Interface d’administration
Each upgrade extending the Elgg\Upgrade\AsynchronousUpgrade
class gets
listed in the admin panel after triggering the site upgrade from the
Administration dashboard.
Lors de l’exécution des mises à niveau, Elgg fournit :
Durée estimée de la mise à niveau
Nombre d’éléments traités
Nombre d’erreurs
Messages d’erreur possibles