Overview

Namespaces

  • GAubry
    • ErrorHandler
    • Helpers
    • Logger
    • Shell
  • Himedia
    • Padocc
      • DB
      • Minifier
      • Numbering
      • Properties
      • Task
        • Base
        • Extended
  • None
  • Psr
    • Log

Classes

  • Backup
  • Call
  • Composer
  • Copy
  • Environment
  • ExternalProperty
  • FillTemplate
  • HTTP
  • Link
  • MkDir
  • Project
  • Property
  • Rename
  • Sync
  • Target
  • Overview
  • Namespace
  • Class
  • Tree
  • Deprecated
  • Todo
  1: <?php
  2: 
  3: namespace Himedia\Padocc\Task\Base;
  4: 
  5: use Himedia\Padocc\AttributeProperties;
  6: use Himedia\Padocc\Task\WithProperties;
  7: use Himedia\Padocc\Task;
  8: 
  9: /**
 10:  * Définit une section (factorisation) adressable via la tâche call.
 11:  * À inclure dans une tâche project.
 12:  *
 13:  * Exemple : <call target="static_content" />...<target name="static_content">...</target>
 14:  *
 15:  * @author Geoffroy AUBRY <gaubry@hi-media.com>
 16:  */
 17: class Target extends WithProperties
 18: {
 19:     /**
 20:      * @var array
 21:      * @see getAvailableTasks()
 22:      */
 23:     private static $aAvailableTasks = array();
 24: 
 25:     /**
 26:      * Liste d'instances de type Task ordonnées constituant la cible.
 27:      * @var Task[]
 28:      */
 29:     protected $aTasks;
 30: 
 31:     /**
 32:      * {@inheritdoc}
 33:      */
 34:     protected function init()
 35:     {
 36:         parent::init();
 37: 
 38:         $this->aAttrProperties = array_merge(
 39:             $this->aAttrProperties,
 40:             array('name' => AttributeProperties::REQUIRED)
 41:         );
 42: 
 43:         $this->oNumbering->addCounterDivision();
 44:         $this->aTasks = $this->getTaskInstances($this->oXMLTask, $this->oProject);
 45:         $this->oNumbering->removeCounterDivision();
 46:     }
 47: 
 48:     /**
 49:      * {@inheritdoc}
 50:      * @codeCoverageIgnore
 51:      */
 52:     public static function getTagName ()
 53:     {
 54:         return 'target';
 55:     }
 56: 
 57:     /**
 58:      * Retourne la liste ordonnée des noeuds XML de type <externalproperty />, sous forme de SimpleXMLElement.
 59:      * Les débusque également dans les noeuds <target /> au travers des <call />.
 60:      *
 61:      * @param \SimpleXMLElement $oSXEProject instance du projet
 62:      * @param \SimpleXMLElement $oNode noeud à explorer à la recherche des propriétés externes
 63:      * @return array la liste ordonnée des noeuds XML de type <externalproperty />, sous forme de SimpleXMLElement.
 64:      * @throws \UnexpectedValueException si noeud <target /> non trouvé ou non unique mais référencé par un
 65:      *      noeud <call />.
 66:      */
 67:     private static function getSXEExternalProperties (\SimpleXMLElement $oSXEProject, \SimpleXMLElement $oNode)
 68:     {
 69:         // Récupération du nom des balises XML :
 70:         $sExtPropertyTagName = ExternalProperty::getTagName();
 71:         $sCallTagName = Call::getTagName();
 72:         $sTargetTagName = Target::getTagName();
 73: 
 74:         $aSXEExtProperties = array();
 75:         /* @var $oSXEChild \SimpleXMLElement */
 76:         foreach ($oNode->children() as $oSXEChild) {
 77:             $sName = (string)$oSXEChild->getName();
 78:             if ($sName === $sCallTagName && isset($oSXEChild['target'])) {
 79:                 $sTargetName = (string)$oSXEChild['target'];
 80:                 $aTargets = $oSXEProject->xpath("//{$sTargetTagName}[@name='$sTargetName']");
 81:                 if (count($aTargets) !== 1) {
 82:                     $sMsg = "Target '$sTargetName' not found or not unique in this project!";
 83:                     throw new \UnexpectedValueException($sMsg);
 84:                 }
 85:                 $aSXEExtProperties = array_merge(
 86:                     $aSXEExtProperties,
 87:                     self::getSXEExternalProperties($oSXEProject, $aTargets[0])
 88:                 );
 89:             } elseif ($sName === $sExtPropertyTagName) {
 90:                 $aSXEExtProperties[] = $oSXEChild;
 91:             }
 92:         }
 93:         return $aSXEExtProperties;
 94:     }
 95: 
 96:     /**
 97:      * Retourne la liste des environnements et de leurs propriétés externes pour le projet spécifié.
 98:      *
 99:      * Exemple de retour : array(
100:      *      'dev' => array(),
101:      *      'qa' => array(
102:      *          'ref' => "Branch or tag to deploy",
103:      *          ...
104:      *      )
105:      * )
106:      *
107:      *
108:      * @param string $sXmlProject XML project path or XML data
109:      * @return array la liste des environnements et de leurs propriétés externes pour le projet spécifié.
110:      * @throws \UnexpectedValueException si fichier XML du projet non trouvé
111:      * @throws \UnexpectedValueException si fichier XML du projet mal formaté
112:      * @throws \UnexpectedValueException si pas d'environnement trouvé
113:      * @throws \UnexpectedValueException si noeud <externalproperty /> invalide
114:      * @throws \UnexpectedValueException si noeud <target /> non trouvé ou non unique mais référencé par un
115:      *      noeud <call />.
116:      */
117:     public static function getAvailableEnvsList ($sXmlProject)
118:     {
119:         $oSXEProject = Project::getSXEProject($sXmlProject);
120:         $aTargets = $oSXEProject->xpath("//env");
121:         if (count($aTargets) === 0) {
122:             throw new \UnexpectedValueException("No environment found in specified project!");
123:         }
124:         $aEnvsList = array();
125:         foreach ($aTargets as $oTarget) {
126:             $aSXEExtProperties = self::getSXEExternalProperties($oSXEProject, $oTarget);
127:             $aExtProperties = array();
128:             foreach ($aSXEExtProperties as $oSXEExtProperty) {
129:                 if (! isset($oSXEExtProperty['name']) || ! isset($oSXEExtProperty['description'])) {
130:                     throw new \UnexpectedValueException("Invalid external property in specified project!");
131:                 }
132:                 $sName = (string)$oSXEExtProperty['name'];
133:                 $sDesc = (string)$oSXEExtProperty['description'];
134:                 $aExtProperties[$sName] = $sDesc;
135:             }
136: 
137:             $sEnvName = (string)$oTarget['name'];
138:             $aEnvsList[$sEnvName] = $aExtProperties;
139:         }
140: 
141:         return $aEnvsList;
142:     }
143: 
144:     /**
145:      * Retourne un tableau associatif décrivant les tâches disponibles.
146:      *
147:      * @throws \RuntimeException si classe inexistante
148:      * @throws \LogicException si collision de nom de tag XML
149:      * @return array tableau associatif des tâches disponibles : array('sTag' => 'sClassName', ...)
150:      */
151:     private static function getAvailableTasks ()
152:     {
153:         if (count(self::$aAvailableTasks) === 0) {
154:             $aAvailableTasks = array();
155:             foreach (array('Base', 'Extended') as $sTaskType) {
156:                 $sTaskPaths = glob(__DIR__ . "/../$sTaskType/*.php");
157:                 foreach ($sTaskPaths as $sTaskPath) {
158:                     $sClassName = strstr(substr(strrchr($sTaskPath, '/'), 1), '.', true);
159:                     $sFullClassName = "Himedia\\Padocc\\Task\\$sTaskType\\$sClassName";
160: 
161:                     if (! class_exists($sFullClassName, true)) {
162:                         throw new \RuntimeException($sFullClassName." doesn't exist!");
163:                     }
164: 
165:                     /* @var $sFullClassName Task */
166:                     $sTag = $sFullClassName::getTagName();
167:                     if (isset($aAvailableTasks[$sTag])) {
168:                         throw new \LogicException("Already defined task tag '$sTag' in '$aAvailableTasks[$sTag]'!");
169:                     } elseif ($sTag != 'project') {
170:                         $aAvailableTasks[$sTag] = $sFullClassName;
171:                     }
172:                 }
173:             }
174:             self::$aAvailableTasks = $aAvailableTasks;
175:         }
176:         return self::$aAvailableTasks;
177:     }
178: 
179:     /**
180:      * Retourne la liste des instances de tâches correspondant à chacune des tâches XML devant être exécutée
181:      * à l'intérieur du noeud XML spécifié.
182:      *
183:      * @param \SimpleXMLElement $oTarget
184:      * @param Project $oProject
185:      * @return array liste d'instances de type Task
186:      * @throws \Exception si tag XML inconnu.
187:      * @see Task
188:      */
189:     private function getTaskInstances (\SimpleXMLElement $oTarget, Project $oProject)
190:     {
191:         $this->getLogger()->info("Initialize tasks of target '" . $this->aAttValues['name'] . "'.");
192:         $aAvailableTasks = self::getAvailableTasks();
193: 
194:         // Mise à plat des tâches car \SimpleXML regroupe celles successives de même nom
195:         // dans un tableau et les autres sont hors tableau :
196:         $aTasks = array();
197:         foreach ($oTarget->children() as $sTag => $mTasks) {
198:             if (is_array($mTasks)) {
199:                 foreach ($mTasks as $oTask) {
200:                     $aTasks[] = array($sTag, $oTask);
201:                 }
202:             } else {
203:                 $aTasks[] = array($sTag, $mTasks);
204:             }
205:         }
206: 
207:         // Création des instances de tâches :
208:         $aTaskInstances = array();
209:         foreach ($aTasks as $aTask) {
210:             list($sTag, $oTask) = $aTask;
211:             if (! isset($aAvailableTasks[$sTag])) {
212:                 throw new \UnexpectedValueException("Unkown task tag: '$sTag'!");
213:             } else {
214:                 $aTaskInstances[] = new $aAvailableTasks[$sTag]($oTask, $oProject, $this->oDIContainer);
215:             }
216:         }
217: 
218:         return $aTaskInstances;
219:     }
220: 
221:     /**
222:      * Vérifie au moyen de tests basiques que la tâche peut être exécutée.
223:      * Lance une exception si tel n'est pas le cas.
224:      *
225:      * Comme toute les tâches sont vérifiées avant que la première ne soit exécutée,
226:      * doit permettre de remonter au plus tôt tout dysfonctionnement.
227:      * Appelé avant la méthode execute().
228:      *
229:      * @throws \UnexpectedValueException en cas d'attribut ou fichier manquant
230:      * @throws \DomainException en cas de valeur non permise
231:      */
232:     public function check ()
233:     {
234:         parent::check();
235: 
236:         if (! empty($this->aAttValues['mailto'])) {
237:             $aSplittedValues = preg_split(
238:                 AttributeProperties::$sMultiValuedSep,
239:                 trim($this->aAttValues['mailto']),
240:                 -1,
241:                 PREG_SPLIT_NO_EMPTY
242:             );
243:             $this->aAttValues['mailto'] = implode(' ', $aSplittedValues);
244:         }
245:     }
246: 
247:     /**
248:      * Prépare la tâche avant exécution : vérifications basiques, analyse des serveurs concernés...
249:      */
250:     public function setUp ()
251:     {
252:         parent::setUp();
253:         $this->getLogger()->info('+++');
254:         foreach ($this->aTasks as $oTask) {
255:             $oTask->setUp();
256:         }
257:         $this->getLogger()->info('---');
258:     }
259: 
260:     /**
261:      * Phase de pré-traitements de l'exécution de la tâche.
262:      * Elle devrait systématiquement commencer par "parent::preExecute();".
263:      * Appelé par execute().
264:      * @see execute()
265:      */
266:     protected function preExecute ()
267:     {
268:         parent::preExecute();
269:         if (! empty($this->aAttValues['mailto'])) {
270:             $this->getLogger()->info('+++[MAILTO] ' . $this->aAttValues['mailto'] . '---');
271:         }
272:     }
273: 
274:     /**
275:      * Phase de traitements centraux de l'exécution de la tâche.
276:      * Elle devrait systématiquement commencer par "parent::centralExecute();".
277:      * Appelé par execute().
278:      * @see execute()
279:      */
280:     protected function centralExecute ()
281:     {
282:         parent::centralExecute();
283:         $this->getLogger()->info('+++');
284:         foreach ($this->aTasks as $oTask) {
285:             $oTask->execute();
286:         }
287:         $this->getLogger()->info('---');
288:     }
289: }
290: 
Platform for Automatized Deployments with pOwerful Concise Configuration API documentation generated by ApiGen 2.8.0