A bunch of new updates from icehrm pro
This commit is contained in:
@@ -3,16 +3,16 @@
|
||||
|
||||
@version V5.11 5 May 2010 (c) 2000-2010 John Lim (jlim#natsoft.com). All rights reserved.
|
||||
Latest version is available at http://adodb.sourceforge.net
|
||||
|
||||
Released under both BSD license and Lesser GPL library license.
|
||||
Whenever there is any discrepancy between the two licenses,
|
||||
|
||||
Released under both BSD license and Lesser GPL library license.
|
||||
Whenever there is any discrepancy between the two licenses,
|
||||
the BSD license will take precedence.
|
||||
|
||||
|
||||
Active Record implementation. Superset of Zend Framework's.
|
||||
|
||||
|
||||
Version 0.92
|
||||
|
||||
See http://www-128.ibm.com/developerworks/java/library/j-cb03076/?ca=dgr-lnxw01ActiveRecord
|
||||
|
||||
See http://www-128.ibm.com/developerworks/java/library/j-cb03076/?ca=dgr-lnxw01ActiveRecord
|
||||
for info on Ruby on Rails Active Record implementation
|
||||
*/
|
||||
|
||||
@@ -44,7 +44,7 @@ class ADODB_Active_Table {
|
||||
|
||||
// $db = database connection
|
||||
// $index = name of index - can be associative, for an example see
|
||||
// http://phplens.com/lens/lensforum/msgs.php?id=17790
|
||||
// http://phplens.com/lens/lensforum/msgs.php?id=17790
|
||||
// returns index into $_ADODB_ACTIVE_DBS
|
||||
function ADODB_SetDatabaseAdapter(&$db, $index=false)
|
||||
{
|
||||
@@ -58,23 +58,23 @@ function ADODB_SetDatabaseAdapter(&$db, $index=false)
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if ($d->db->_connectionID === $db->_connectionID && $db->database == $d->db->database) {
|
||||
if ($d->db->_connectionID === $db->_connectionID && $db->database == $d->db->database) {
|
||||
$obj = $d;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ($index == false) $index = sizeof($_ADODB_ACTIVE_DBS);
|
||||
|
||||
|
||||
if(!isset($obj)) {
|
||||
$obj = new ADODB_Active_DB();
|
||||
$obj->db = $db;
|
||||
$obj->tables = array();
|
||||
$obj->tables = array();
|
||||
}
|
||||
|
||||
|
||||
$_ADODB_ACTIVE_DBS[$index] = $obj;
|
||||
|
||||
|
||||
return $index;
|
||||
}
|
||||
|
||||
@@ -82,8 +82,8 @@ function ADODB_SetDatabaseAdapter(&$db, $index=false)
|
||||
class ADODB_Active_Record {
|
||||
static $_changeNames = true; // dynamically pluralize table names
|
||||
static $_quoteNames = false;
|
||||
|
||||
static $_foreignSuffix = '_id'; //
|
||||
|
||||
static $_foreignSuffix = '_id'; //
|
||||
var $_dbat; // associative index pointing to ADODB_Active_DB eg. $ADODB_Active_DBS[_dbat]
|
||||
var $_table; // tablename, if set in class definition then use it as table name
|
||||
var $_tableat; // associative index pointing to ADODB_Active_Table, eg $ADODB_Active_DBS[_dbat]->tables[$this->_tableat]
|
||||
@@ -103,7 +103,7 @@ class ADODB_Active_Record {
|
||||
}
|
||||
|
||||
// should be static
|
||||
static function SetDatabaseAdapter(&$db, $index=false)
|
||||
static function SetDatabaseAdapter(&$db, $index=false)
|
||||
{
|
||||
//error_log("Coming into ".self::_pluralize(get_called_class())."'s SetDatabaseAdapter where ".get_class());
|
||||
if(!$index || !isset($index)) {
|
||||
@@ -111,19 +111,19 @@ class ADODB_Active_Record {
|
||||
}
|
||||
return ADODB_SetDatabaseAdapter($db, $index);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public function __set($name, $value)
|
||||
{
|
||||
$name = str_replace(' ', '_', $name);
|
||||
$this->$name = $value;
|
||||
}
|
||||
|
||||
|
||||
// php5 constructor
|
||||
function __construct($table = false, $pkeyarr=false, $db=false)
|
||||
{
|
||||
global $ADODB_ASSOC_CASE,$_ADODB_ACTIVE_DBS;
|
||||
|
||||
|
||||
if ($db == false && is_object($pkeyarr)) {
|
||||
$db = $pkeyarr;
|
||||
$pkeyarr = false;
|
||||
@@ -143,9 +143,9 @@ class ADODB_Active_Record {
|
||||
if(isset($_ADODB_ACTIVE_DBS[self::_pluralize(get_called_class())])) {
|
||||
$this->_dbat = self::_pluralize(get_called_class());
|
||||
} else {
|
||||
$this->_dbat = key($_ADODB_ACTIVE_DBS);
|
||||
$this->_dbat = key($_ADODB_ACTIVE_DBS);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
$this->_table = $table;
|
||||
@@ -153,13 +153,13 @@ class ADODB_Active_Record {
|
||||
|
||||
$this->UpdateActiveTable($pkeyarr);
|
||||
}
|
||||
|
||||
|
||||
function __wakeup()
|
||||
{
|
||||
$class = get_class($this);
|
||||
new $class;
|
||||
}
|
||||
|
||||
|
||||
static function _pluralize($table)
|
||||
{
|
||||
if (!ADODB_Active_Record::$_changeNames) return $table;
|
||||
@@ -170,26 +170,26 @@ class ADODB_Active_Record {
|
||||
$lastc2 = substr($ut,$len-2);
|
||||
switch ($lastc) {
|
||||
case 'S':
|
||||
return $table.'es';
|
||||
return $table.'es';
|
||||
case 'Y':
|
||||
return substr($table,0,$len-1).'ies';
|
||||
case 'X':
|
||||
case 'X':
|
||||
return $table.'es';
|
||||
case 'H':
|
||||
case 'H':
|
||||
if ($lastc2 == 'CH' || $lastc2 == 'SH')
|
||||
return $table.'es';
|
||||
default:
|
||||
return $table.'s';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// CFR Lamest singular inflector ever - @todo Make it real!
|
||||
// Note: There is an assumption here...and it is that the argument's length >= 4
|
||||
function _singularize($tables)
|
||||
{
|
||||
|
||||
|
||||
if (!ADODB_Active_Record::$_changeNames) return $table;
|
||||
|
||||
|
||||
$ut = strtoupper($tables);
|
||||
$len = strlen($tables);
|
||||
if($ut[$len-1] != 'S')
|
||||
@@ -221,14 +221,14 @@ class ADODB_Active_Record {
|
||||
$table->_hasMany[$foreignRef] = $ar;
|
||||
# $this->$foreignRef = $this->_hasMany[$foreignRef]; // WATCHME Removed assignment by ref. to please __get()
|
||||
}
|
||||
|
||||
|
||||
// use when you don't want ADOdb to auto-pluralize tablename
|
||||
static function TableHasMany($table, $foreignRef, $foreignKey = false, $foreignClass = 'ADODB_Active_Record')
|
||||
{
|
||||
$ar = new ADODB_Active_Record($table);
|
||||
$ar->hasMany($foreignRef, $foreignKey, $foreignClass);
|
||||
}
|
||||
|
||||
|
||||
// use when you don't want ADOdb to auto-pluralize tablename
|
||||
static function TableKeyHasMany($table, $tablePKey, $foreignRef, $foreignKey = false, $foreignClass = 'ADODB_Active_Record')
|
||||
{
|
||||
@@ -236,8 +236,8 @@ class ADODB_Active_Record {
|
||||
$ar = new ADODB_Active_Record($table,$tablePKey);
|
||||
$ar->hasMany($foreignRef, $foreignKey, $foreignClass);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// use when you want ADOdb to auto-pluralize tablename for you. Note that the class must already be defined.
|
||||
// e.g. class Person will generate relationship for table Persons
|
||||
static function ClassHasMany($parentclass, $foreignRef, $foreignKey = false, $foreignClass = 'ADODB_Active_Record')
|
||||
@@ -245,7 +245,7 @@ class ADODB_Active_Record {
|
||||
$ar = new $parentclass();
|
||||
$ar->hasMany($foreignRef, $foreignKey, $foreignClass);
|
||||
}
|
||||
|
||||
|
||||
|
||||
function belongsTo($foreignRef,$foreignKey=false, $parentKey='', $parentClass = 'ADODB_Active_Record')
|
||||
{
|
||||
@@ -256,24 +256,24 @@ class ADODB_Active_Record {
|
||||
$ar->parentKey = $parentKey;
|
||||
$ar->UpdateActiveTable();
|
||||
$ar->foreignKey = ($foreignKey) ? $foreignKey : $foreignRef.ADODB_Active_Record::$_foreignSuffix;
|
||||
|
||||
|
||||
$table =& $this->TableInfo();
|
||||
$table->_belongsTo[$foreignRef] = $ar;
|
||||
# $this->$foreignRef = $this->_belongsTo[$foreignRef];
|
||||
}
|
||||
|
||||
|
||||
static function ClassBelongsTo($class, $foreignRef, $foreignKey=false, $parentKey='', $parentClass = 'ADODB_Active_Record')
|
||||
{
|
||||
$ar = new $class();
|
||||
$ar->belongsTo($foreignRef, $foreignKey, $parentKey, $parentClass);
|
||||
}
|
||||
|
||||
|
||||
static function TableBelongsTo($table, $foreignRef, $foreignKey=false, $parentKey='', $parentClass = 'ADODB_Active_Record')
|
||||
{
|
||||
$ar = new ADOdb_Active_Record($table);
|
||||
$ar->belongsTo($foreignRef, $foreignKey, $parentKey, $parentClass);
|
||||
}
|
||||
|
||||
|
||||
static function TableKeyBelongsTo($table, $tablePKey, $foreignRef, $foreignKey=false, $parentKey='', $parentClass = 'ADODB_Active_Record')
|
||||
{
|
||||
if (!is_array($tablePKey)) $tablePKey = array($tablePKey);
|
||||
@@ -284,8 +284,8 @@ class ADODB_Active_Record {
|
||||
|
||||
/**
|
||||
* __get Access properties - used for lazy loading
|
||||
*
|
||||
* @param mixed $name
|
||||
*
|
||||
* @param mixed $name
|
||||
* @access protected
|
||||
* @return mixed
|
||||
*/
|
||||
@@ -293,9 +293,9 @@ class ADODB_Active_Record {
|
||||
{
|
||||
return $this->LoadRelations($name, '', -1, -1);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param string $name
|
||||
* @param string $whereOrderBy : eg. ' AND field1 = value ORDER BY field2'
|
||||
* @param offset
|
||||
* @param limit
|
||||
@@ -307,12 +307,12 @@ class ADODB_Active_Record {
|
||||
$table = $this->TableInfo();
|
||||
if ($limit >= 0) $extras['limit'] = $limit;
|
||||
if ($offset >= 0) $extras['offset'] = $offset;
|
||||
|
||||
if (strlen($whereOrderBy))
|
||||
|
||||
if (strlen($whereOrderBy))
|
||||
if (!preg_match('/^[ \n\r]*AND/i',$whereOrderBy))
|
||||
if (!preg_match('/^[ \n\r]*ORDER[ \n\r]/i',$whereOrderBy))
|
||||
$whereOrderBy = 'AND '.$whereOrderBy;
|
||||
|
||||
|
||||
if(!empty($table->_belongsTo[$name]))
|
||||
{
|
||||
$obj = $table->_belongsTo[$name];
|
||||
@@ -323,7 +323,7 @@ class ADODB_Active_Record {
|
||||
{
|
||||
if ($obj->parentKey) $key = $obj->parentKey;
|
||||
else $key = reset($table->keys);
|
||||
|
||||
|
||||
$arrayOfOne = $obj->Find($key.'='.$this->$columnName.' '.$whereOrderBy,false,false,$extras);
|
||||
if ($arrayOfOne) {
|
||||
$this->$name = $arrayOfOne[0];
|
||||
@@ -332,7 +332,7 @@ class ADODB_Active_Record {
|
||||
}
|
||||
}
|
||||
if(!empty($table->_hasMany[$name]))
|
||||
{
|
||||
{
|
||||
$obj = $table->_hasMany[$name];
|
||||
$key = reset($table->keys);
|
||||
$id = @$this->$key;
|
||||
@@ -345,11 +345,11 @@ class ADODB_Active_Record {
|
||||
$this->$name = $objs;
|
||||
return $objs;
|
||||
}
|
||||
|
||||
|
||||
return array();
|
||||
}
|
||||
//////////////////////////////////
|
||||
|
||||
|
||||
// update metadata
|
||||
function UpdateActiveTable($pkeys=false,$forceUpdate=false)
|
||||
{
|
||||
@@ -365,7 +365,7 @@ class ADODB_Active_Record {
|
||||
|
||||
$acttab = $tables[$tableat];
|
||||
foreach($acttab->flds as $name => $fld) {
|
||||
if ($ADODB_ACTIVE_DEFVALS && isset($fld->default_value))
|
||||
if ($ADODB_ACTIVE_DEFVALS && isset($fld->default_value))
|
||||
$this->$name = $fld->default_value;
|
||||
else
|
||||
$this->$name = null;
|
||||
@@ -379,19 +379,19 @@ class ADODB_Active_Record {
|
||||
@flock($fp, LOCK_SH);
|
||||
$acttab = unserialize(fread($fp,100000));
|
||||
fclose($fp);
|
||||
if ($acttab->_created + $ADODB_ACTIVE_CACHESECS - (abs(rand()) % 16) > time()) {
|
||||
if ($acttab->_created + $ADODB_ACTIVE_CACHESECS - (abs(rand()) % 16) > time()) {
|
||||
// abs(rand()) randomizes deletion, reducing contention to delete/refresh file
|
||||
// ideally, you should cache at least 32 secs
|
||||
|
||||
|
||||
foreach($acttab->flds as $name => $fld) {
|
||||
if ($ADODB_ACTIVE_DEFVALS && isset($fld->default_value))
|
||||
if ($ADODB_ACTIVE_DEFVALS && isset($fld->default_value))
|
||||
$this->$name = $fld->default_value;
|
||||
else
|
||||
$this->$name = null;
|
||||
}
|
||||
|
||||
|
||||
$activedb->tables[$table] = $acttab;
|
||||
|
||||
|
||||
//if ($db->debug) ADOConnection::outp("Reading cached active record file: $fname");
|
||||
return;
|
||||
} else if ($db->debug) {
|
||||
@@ -400,18 +400,18 @@ class ADODB_Active_Record {
|
||||
}
|
||||
$activetab = new ADODB_Active_Table();
|
||||
$activetab->name = $table;
|
||||
|
||||
|
||||
$save = $ADODB_FETCH_MODE;
|
||||
$ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
|
||||
if ($db->fetchMode !== false) $savem = $db->SetFetchMode(false);
|
||||
|
||||
|
||||
$cols = $db->MetaColumns($table);
|
||||
|
||||
|
||||
if (isset($savem)) $db->SetFetchMode($savem);
|
||||
$ADODB_FETCH_MODE = $save;
|
||||
|
||||
|
||||
if (!$cols) {
|
||||
$this->Error("Invalid table name: $table",'UpdateActiveTable');
|
||||
$this->Error("Invalid table name: $table",'UpdateActiveTable');
|
||||
return false;
|
||||
}
|
||||
$fld = reset($cols);
|
||||
@@ -421,14 +421,14 @@ class ADODB_Active_Record {
|
||||
foreach($cols as $name => $fld) {
|
||||
if (!empty($fld->primary_key)) $pkeys[] = $name;
|
||||
}
|
||||
} else
|
||||
} else
|
||||
$pkeys = $this->GetPrimaryKeys($db, $table);
|
||||
}
|
||||
if (empty($pkeys)) {
|
||||
$this->Error("No primary key found for table $table",'UpdateActiveTable');
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
$attr = array();
|
||||
$keys = array();
|
||||
$ADODB_ASSOC_CASE = 2;
|
||||
@@ -446,18 +446,18 @@ class ADODB_Active_Record {
|
||||
$keys[strtolower($name)] = strtolower($name);
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
|
||||
case 1:
|
||||
foreach($cols as $name => $fldobj) {
|
||||
$name = strtoupper($name);
|
||||
|
||||
|
||||
if ($ADODB_ACTIVE_DEFVALS && isset($fldobj->default_value))
|
||||
$this->$name = $fldobj->default_value;
|
||||
else
|
||||
$this->$name = null;
|
||||
$attr[$name] = $fldobj;
|
||||
}
|
||||
|
||||
|
||||
foreach($pkeys as $k => $name) {
|
||||
$keys[strtoupper($name)] = strtoupper($name);
|
||||
}
|
||||
@@ -465,7 +465,7 @@ class ADODB_Active_Record {
|
||||
default:
|
||||
foreach($cols as $name => $fldobj) {
|
||||
$name = ($fldobj->name);
|
||||
|
||||
|
||||
if ($ADODB_ACTIVE_DEFVALS && isset($fldobj->default_value))
|
||||
$this->$name = $fldobj->default_value;
|
||||
else
|
||||
@@ -477,7 +477,7 @@ class ADODB_Active_Record {
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
$activetab->keys = $keys;
|
||||
$activetab->flds = $attr;
|
||||
|
||||
@@ -489,58 +489,58 @@ class ADODB_Active_Record {
|
||||
}
|
||||
if (isset($activedb->tables[$table])) {
|
||||
$oldtab = $activedb->tables[$table];
|
||||
|
||||
|
||||
if ($oldtab) $activetab->_belongsTo = $oldtab->_belongsTo;
|
||||
if ($oldtab) $activetab->_hasMany = $oldtab->_hasMany;
|
||||
}
|
||||
$activedb->tables[$table] = $activetab;
|
||||
}
|
||||
|
||||
|
||||
function GetPrimaryKeys(&$db, $table)
|
||||
{
|
||||
return $db->MetaPrimaryKeys($table);
|
||||
}
|
||||
|
||||
// error handler for both PHP4+5.
|
||||
|
||||
// error handler for both PHP4+5.
|
||||
function Error($err,$fn)
|
||||
{
|
||||
global $_ADODB_ACTIVE_DBS;
|
||||
|
||||
|
||||
$fn = get_class($this).'::'.$fn;
|
||||
$this->_lasterr = $fn.': '.$err;
|
||||
|
||||
|
||||
if ($this->_dbat < 0) $db = false;
|
||||
else {
|
||||
$activedb = $_ADODB_ACTIVE_DBS[$this->_dbat];
|
||||
$db = $activedb->db;
|
||||
}
|
||||
|
||||
if (function_exists('adodb_throw')) {
|
||||
|
||||
if (function_exists('adodb_throw')) {
|
||||
if (!$db) adodb_throw('ADOdb_Active_Record', $fn, -1, $err, 0, 0, false);
|
||||
else adodb_throw($db->databaseType, $fn, -1, $err, 0, 0, $db);
|
||||
} else
|
||||
if (!$db || $db->debug) ADOConnection::outp($this->_lasterr);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
// return last error message
|
||||
function ErrorMsg()
|
||||
{
|
||||
if (!function_exists('adodb_throw')) {
|
||||
if ($this->_dbat < 0) $db = false;
|
||||
else $db = $this->DB();
|
||||
|
||||
|
||||
// last error could be database error too
|
||||
if ($db && $db->ErrorMsg()) return $db->ErrorMsg();
|
||||
}
|
||||
return $this->_lasterr;
|
||||
}
|
||||
|
||||
function ErrorNo()
|
||||
|
||||
function ErrorNo()
|
||||
{
|
||||
if ($this->_dbat < 0) return -9999; // no database connection...
|
||||
$db = $this->DB();
|
||||
|
||||
|
||||
return (int) $db->ErrorNo();
|
||||
}
|
||||
|
||||
@@ -549,7 +549,7 @@ class ADODB_Active_Record {
|
||||
function DB()
|
||||
{
|
||||
global $_ADODB_ACTIVE_DBS;
|
||||
|
||||
|
||||
if ($this->_dbat < 0) {
|
||||
$false = false;
|
||||
$this->Error("No database connection set: use ADOdb_Active_Record::SetDatabaseAdaptor(\$db)", "DB");
|
||||
@@ -559,7 +559,7 @@ class ADODB_Active_Record {
|
||||
$db = $activedb->db;
|
||||
return $db;
|
||||
}
|
||||
|
||||
|
||||
// retrieve ADODB_Active_Table
|
||||
function &TableInfo()
|
||||
{
|
||||
@@ -568,8 +568,8 @@ class ADODB_Active_Record {
|
||||
$table = $activedb->tables[$this->_tableat];
|
||||
return $table;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// I have an ON INSERT trigger on a table that sets other columns in the table.
|
||||
// So, I find that for myTable, I want to reload an active record after saving it. -- Malcolm Cook
|
||||
function Reload()
|
||||
@@ -580,21 +580,21 @@ class ADODB_Active_Record {
|
||||
return($this->Load($where));
|
||||
}
|
||||
|
||||
|
||||
|
||||
// set a numeric array (using natural table field ordering) as object properties
|
||||
function Set(&$row)
|
||||
{
|
||||
global $ACTIVE_RECORD_SAFETY;
|
||||
|
||||
|
||||
$db = $this->DB();
|
||||
|
||||
|
||||
if (!$row) {
|
||||
$this->_saved = false;
|
||||
$this->_saved = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
$this->_saved = true;
|
||||
|
||||
|
||||
$table = $this->TableInfo();
|
||||
if ($ACTIVE_RECORD_SAFETY && sizeof($table->flds) != sizeof($row)) {
|
||||
# <AP>
|
||||
@@ -613,7 +613,7 @@ class ADODB_Active_Record {
|
||||
}
|
||||
else
|
||||
$keys = array_keys($row);
|
||||
|
||||
|
||||
# <AP>
|
||||
reset($keys);
|
||||
$this->_original = array();
|
||||
@@ -627,7 +627,7 @@ class ADODB_Active_Record {
|
||||
# </AP>
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// get last inserted id for INSERT
|
||||
function LastInsertID(&$db,$fieldname)
|
||||
{
|
||||
@@ -635,32 +635,32 @@ class ADODB_Active_Record {
|
||||
$val = $db->Insert_ID($this->_table,$fieldname);
|
||||
else
|
||||
$val = false;
|
||||
|
||||
|
||||
if (is_null($val) || $val === false) {
|
||||
// this might not work reliably in multi-user environment
|
||||
return $db->GetOne("select max(".$fieldname.") from ".$this->_table);
|
||||
}
|
||||
return $val;
|
||||
}
|
||||
|
||||
|
||||
// quote data in where clause
|
||||
function doquote(&$db, $val,$t)
|
||||
{
|
||||
switch($t) {
|
||||
case 'L':
|
||||
if (strpos($db->databaseType,'postgres') !== false) return $db->qstr($val);
|
||||
case 'D':
|
||||
case 'D':
|
||||
case 'T':
|
||||
if (empty($val)) return 'null';
|
||||
|
||||
case 'B':
|
||||
|
||||
case 'B':
|
||||
case 'N':
|
||||
case 'C':
|
||||
case 'X':
|
||||
if (is_null($val)) return 'null';
|
||||
|
||||
if (strlen($val)>1 &&
|
||||
(strncmp($val,"'",1) != 0 || substr($val,strlen($val)-1,1) != "'")) {
|
||||
|
||||
if (strlen($val)>1 &&
|
||||
(strncmp($val,"'",1) != 0 || substr($val,strlen($val)-1,1) != "'")) {
|
||||
return $db->qstr($val);
|
||||
break;
|
||||
}
|
||||
@@ -669,13 +669,13 @@ class ADODB_Active_Record {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// generate where clause for an UPDATE/SELECT
|
||||
function GenWhere(&$db, &$table)
|
||||
{
|
||||
$keys = $table->keys;
|
||||
$parr = array();
|
||||
|
||||
|
||||
foreach($keys as $k) {
|
||||
$f = $table->flds[$k];
|
||||
if ($f) {
|
||||
@@ -684,17 +684,17 @@ class ADODB_Active_Record {
|
||||
}
|
||||
return implode(' and ', $parr);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
function _QName($n,$db=false)
|
||||
{
|
||||
if (!ADODB_Active_Record::$_quoteNames) return $n;
|
||||
if (!$db) $db = $this->DB(); if (!$db) return false;
|
||||
return $db->nameQuote.$n.$db->nameQuote;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------ Public functions below
|
||||
|
||||
|
||||
function Load($where=null,$bindarr=false)
|
||||
{
|
||||
$this->_where = $where;
|
||||
@@ -705,31 +705,31 @@ class ADODB_Active_Record {
|
||||
}
|
||||
return $this->LoadFromRawQuery($qry, $bindarr);
|
||||
}
|
||||
|
||||
|
||||
function LoadFromRawQuery($qry, $bindarr=false) {
|
||||
global $ADODB_FETCH_MODE;
|
||||
|
||||
|
||||
$db = $this->DB(); if (!$db) return false;
|
||||
|
||||
|
||||
$save = $ADODB_FETCH_MODE;
|
||||
$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
|
||||
if ($db->fetchMode !== false) $savem = $db->SetFetchMode(false);
|
||||
|
||||
|
||||
$row = $db->GetRow($qry,$bindarr);
|
||||
|
||||
|
||||
if (isset($savem)) $db->SetFetchMode($savem);
|
||||
$ADODB_FETCH_MODE = $save;
|
||||
|
||||
|
||||
return $this->Set($row);
|
||||
}
|
||||
|
||||
|
||||
# useful for multiple record inserts
|
||||
# see http://phplens.com/lens/lensforum/msgs.php?id=17795
|
||||
function Reset()
|
||||
{
|
||||
$this->_where=null;
|
||||
$this->_saved = false;
|
||||
$this->_lasterr = false;
|
||||
$this->_saved = false;
|
||||
$this->_lasterr = false;
|
||||
$this->_original = false;
|
||||
$vars=get_object_vars($this);
|
||||
foreach($vars as $k=>$v){
|
||||
@@ -740,24 +740,24 @@ class ADODB_Active_Record {
|
||||
$this->foreignName=strtolower(get_class($this));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// false on error
|
||||
function Save()
|
||||
{
|
||||
if ($this->_saved) $ok = $this->Update();
|
||||
else $ok = $this->Insert();
|
||||
|
||||
|
||||
return $ok;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// false on error
|
||||
function Insert()
|
||||
{
|
||||
$db = $this->DB(); if (!$db) return false;
|
||||
$cnt = 0;
|
||||
$table = $this->TableInfo();
|
||||
|
||||
|
||||
$valarr = array();
|
||||
$names = array();
|
||||
$valstr = array();
|
||||
@@ -771,7 +771,7 @@ class ADODB_Active_Record {
|
||||
$cnt += 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (empty($names)){
|
||||
foreach($table->flds as $name=>$fld) {
|
||||
$valarr[] = null;
|
||||
@@ -782,7 +782,7 @@ class ADODB_Active_Record {
|
||||
}
|
||||
$sql = 'INSERT INTO '.$this->_table."(".implode(',',$names).') VALUES ('.implode(',',$valstr).')';
|
||||
$ok = $db->Execute($sql,$valarr);
|
||||
|
||||
|
||||
if ($ok) {
|
||||
$this->_saved = true;
|
||||
$autoinc = false;
|
||||
@@ -797,32 +797,32 @@ class ADODB_Active_Record {
|
||||
$this->$k = $this->LastInsertID($db,$k);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$this->_original = $valarr;
|
||||
return !empty($ok);
|
||||
}
|
||||
|
||||
|
||||
function Delete()
|
||||
{
|
||||
$db = $this->DB(); if (!$db) return false;
|
||||
$table = $this->TableInfo();
|
||||
|
||||
|
||||
$where = $this->GenWhere($db,$table);
|
||||
$sql = 'DELETE FROM '.$this->_table.' WHERE '.$where;
|
||||
$ok = $db->Execute($sql);
|
||||
|
||||
|
||||
return $ok ? true : false;
|
||||
}
|
||||
|
||||
|
||||
protected function intify($ret) {
|
||||
if(is_numeric($ret)) {
|
||||
return intval($ret);
|
||||
} else {
|
||||
return $ret;
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
function Aggregate($function, $column, $whereGroupBy, $bindarr=false) {
|
||||
if(!in_array($function, ADODB_Active_Record::$_supportedAggregateFunctions)) {
|
||||
throw new InvalidArgumentException("Unknown Aggregate Function $function");
|
||||
@@ -833,11 +833,11 @@ class ADODB_Active_Record {
|
||||
$db = $this->DB(); if (!$db || empty($this->_table)) return false;
|
||||
return $db->GetOne("select $function($column) from ".$this->_table." where ". $whereGroupBy, $bindarr);
|
||||
}
|
||||
|
||||
|
||||
function Count($whereGroupBy, $bindarr=false) {
|
||||
return $this->intify( $this->Aggregate("count", "*", $whereGroupBy, $bindarr) );
|
||||
}
|
||||
|
||||
|
||||
function CountDistinct($column, $whereGroupBy, $bindarr=false) {
|
||||
if(!in_array($column, $this->GetAttributeNames())) {
|
||||
throw new InvalidArgumentException("Unknown Column for CountDistinct $column");
|
||||
@@ -845,7 +845,7 @@ class ADODB_Active_Record {
|
||||
$db = $this->DB(); if (!$db || empty($this->_table)) return false;
|
||||
return $this->intify( $db->GetOne("select count(distinct($column)) from ".$this->_table." where ". $whereGroupBy, $bindarr) );
|
||||
}
|
||||
|
||||
|
||||
// returns an array of active record objects
|
||||
function Find($whereOrderBy,$bindarr=false,$pkeysArr=false,$extra=array())
|
||||
{
|
||||
@@ -853,7 +853,7 @@ class ADODB_Active_Record {
|
||||
$arr = $db->GetActiveRecordsClass(get_class($this),$this->_table, $whereOrderBy,$bindarr,$pkeysArr,$extra);
|
||||
return $arr;
|
||||
}
|
||||
|
||||
|
||||
// returns an array of active record objects
|
||||
function FindFromRawQuery($query,$bindarr=false,$pkeysArr=false,$extra=array())
|
||||
{
|
||||
@@ -861,17 +861,17 @@ class ADODB_Active_Record {
|
||||
$arr = $db->GetActiveRecordsClass2(get_class($this),$this->_table, $query,$bindarr,$pkeysArr,$extra);
|
||||
return $arr;
|
||||
}
|
||||
|
||||
|
||||
// returns 0 on error, 1 on update, 2 on insert
|
||||
function Replace()
|
||||
{
|
||||
global $ADODB_ASSOC_CASE;
|
||||
|
||||
|
||||
$db = $this->DB(); if (!$db) return false;
|
||||
$table = $this->TableInfo();
|
||||
|
||||
|
||||
$pkey = $table->keys;
|
||||
|
||||
|
||||
foreach($table->flds as $name=>$fld) {
|
||||
$val = $this->$name;
|
||||
/*
|
||||
@@ -887,24 +887,24 @@ class ADODB_Active_Record {
|
||||
if (is_null($val) && !empty($fld->auto_increment)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (is_array($val)) continue;
|
||||
|
||||
|
||||
$t = $db->MetaType($fld->type);
|
||||
$arr[$name] = $this->doquote($db,$val,$t);
|
||||
$valarr[] = $val;
|
||||
}
|
||||
|
||||
|
||||
if (!is_array($pkey)) $pkey = array($pkey);
|
||||
|
||||
|
||||
if ($ADODB_ASSOC_CASE == 0)
|
||||
|
||||
|
||||
if ($ADODB_ASSOC_CASE == 0)
|
||||
foreach($pkey as $k => $v)
|
||||
$pkey[$k] = strtolower($v);
|
||||
elseif ($ADODB_ASSOC_CASE == 1)
|
||||
elseif ($ADODB_ASSOC_CASE == 1)
|
||||
foreach($pkey as $k => $v)
|
||||
$pkey[$k] = strtoupper($v);
|
||||
|
||||
|
||||
$ok = $db->Replace($this->_table,$arr,$pkey);
|
||||
if ($ok) {
|
||||
$this->_saved = true; // 1= update 2=insert
|
||||
@@ -921,9 +921,9 @@ class ADODB_Active_Record {
|
||||
$this->$k = $this->LastInsertID($db,$k);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$this->_original = $valarr;
|
||||
}
|
||||
}
|
||||
return $ok;
|
||||
}
|
||||
|
||||
@@ -932,14 +932,14 @@ class ADODB_Active_Record {
|
||||
{
|
||||
$db = $this->DB(); if (!$db) return false;
|
||||
$table = $this->TableInfo();
|
||||
|
||||
|
||||
$where = $this->GenWhere($db, $table);
|
||||
|
||||
|
||||
if (!$where) {
|
||||
$this->error("Where missing for table $table", "Update");
|
||||
return false;
|
||||
}
|
||||
$valarr = array();
|
||||
$valarr = array();
|
||||
$neworig = array();
|
||||
$pairs = array();
|
||||
$i = -1;
|
||||
@@ -948,10 +948,10 @@ class ADODB_Active_Record {
|
||||
$i += 1;
|
||||
$val = $this->$name;
|
||||
$neworig[] = $val;
|
||||
|
||||
if (isset($table->keys[$name]) || is_array($val))
|
||||
|
||||
if (isset($table->keys[$name]) || is_array($val))
|
||||
continue;
|
||||
|
||||
|
||||
if (is_null($val)) {
|
||||
if (isset($fld->not_null) && $fld->not_null) {
|
||||
if (isset($fld->default_value) && strlen($fld->default_value)) continue;
|
||||
@@ -969,8 +969,8 @@ class ADODB_Active_Record {
|
||||
$pairs[] = $this->_QName($name,$db).'='.$db->Param($cnt);
|
||||
$cnt += 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if (!$cnt) return -1;
|
||||
$sql = 'UPDATE '.$this->_table." SET ".implode(",",$pairs)." WHERE ".$where;
|
||||
$ok = $db->Execute($sql,$valarr);
|
||||
@@ -980,21 +980,21 @@ class ADODB_Active_Record {
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
function GetAttributeNames()
|
||||
{
|
||||
$table = $this->TableInfo();
|
||||
if (!$table) return false;
|
||||
return array_keys($table->flds);
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
function adodb_GetActiveRecordsClass(&$db, $class, $table,$whereOrderBy,$bindarr, $primkeyArr,
|
||||
$extra)
|
||||
{
|
||||
$qry = "select * from ".$table;
|
||||
|
||||
|
||||
if (!empty($whereOrderBy)) {
|
||||
$qry .= ' WHERE '.$whereOrderBy;
|
||||
}
|
||||
@@ -1006,7 +1006,7 @@ function adodb_GetActiveRecordsClass2(&$db, $class, $table, $qry, $bindarr, $pri
|
||||
{
|
||||
global $_ADODB_ACTIVE_DBS;
|
||||
|
||||
|
||||
|
||||
$save = $db->SetFetchMode(ADODB_FETCH_NUM);
|
||||
if(isset($extra['limit']))
|
||||
{
|
||||
@@ -1027,13 +1027,13 @@ function adodb_GetActiveRecordsClass2(&$db, $class, $table, $qry, $bindarr, $pri
|
||||
}
|
||||
|
||||
$db->SetFetchMode($save);
|
||||
|
||||
|
||||
$false = false;
|
||||
|
||||
if ($rows === false) {
|
||||
|
||||
if ($rows === false) {
|
||||
return $false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (!class_exists($class)) {
|
||||
$db->outp_throw("Unknown class $class in GetActiveRecordsClass()",'GetActiveRecordsClass');
|
||||
@@ -1047,7 +1047,7 @@ function adodb_GetActiveRecordsClass2(&$db, $class, $table, $qry, $bindarr, $pri
|
||||
$arrRef = array();
|
||||
$bTos = array(); // Will store belongTo's indices if any
|
||||
foreach($rows as $row) {
|
||||
|
||||
|
||||
$obj = new $class($table,$primkeyArr,$db);
|
||||
if ($obj->ErrorNo()){
|
||||
$db->_errorMsg = $obj->ErrorMsg();
|
||||
@@ -1055,7 +1055,7 @@ function adodb_GetActiveRecordsClass2(&$db, $class, $table, $qry, $bindarr, $pri
|
||||
}
|
||||
$obj->Set($row);
|
||||
$arr[] = $obj;
|
||||
} // foreach($rows as $row)
|
||||
} // foreach($rows as $row)
|
||||
|
||||
return $arr;
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
../../src
|
||||
157
core/lib/composer/vendor/consolidation/config/scenarios/symfony2/src/Config.php
vendored
Normal file
157
core/lib/composer/vendor/consolidation/config/scenarios/symfony2/src/Config.php
vendored
Normal file
@@ -0,0 +1,157 @@
|
||||
<?php
|
||||
|
||||
namespace Consolidation\Config;
|
||||
|
||||
use Dflydev\DotAccessData\Data;
|
||||
|
||||
class Config implements ConfigInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @var Data
|
||||
*/
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* TODO: make this private in 2.0 to prevent being saved as an array
|
||||
* Making private now breaks backward compatibility
|
||||
*
|
||||
* @var Data
|
||||
*/
|
||||
protected $defaults;
|
||||
|
||||
/**
|
||||
* Create a new configuration object, and initialize it with
|
||||
* the provided nested array containing configuration data.
|
||||
*
|
||||
* @param array $data - Config data to store
|
||||
*/
|
||||
public function __construct(array $data = null)
|
||||
{
|
||||
$this->config = new Data($data);
|
||||
$this->setDefaults(new Data());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function has($key)
|
||||
{
|
||||
return ($this->config->has($key));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function get($key, $defaultFallback = null)
|
||||
{
|
||||
if ($this->has($key)) {
|
||||
return $this->config->get($key);
|
||||
}
|
||||
return $this->getDefault($key, $defaultFallback);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function set($key, $value)
|
||||
{
|
||||
$this->config->set($key, $value);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function import($data)
|
||||
{
|
||||
return $this->replace($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function replace($data)
|
||||
{
|
||||
$this->config = new Data($data);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function combine($data)
|
||||
{
|
||||
if (!empty($data)) {
|
||||
$this->config->import($data, true);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function export()
|
||||
{
|
||||
return $this->config->export();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function hasDefault($key)
|
||||
{
|
||||
return $this->getDefaults()->has($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDefault($key, $defaultFallback = null)
|
||||
{
|
||||
return $this->hasDefault($key) ? $this->getDefaults()->get($key) : $defaultFallback;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setDefault($key, $value)
|
||||
{
|
||||
$this->getDefaults()->set($key, $value);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the class $defaults property and ensure it's a Data object
|
||||
* TODO: remove Data object validation in 2.0
|
||||
*
|
||||
* @return Data
|
||||
*/
|
||||
protected function getDefaults()
|
||||
{
|
||||
// Ensure $this->defaults is a Data object (not an array)
|
||||
if (!$this->defaults instanceof Data) {
|
||||
$this->setDefaults($this->defaults);
|
||||
}
|
||||
return $this->defaults;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the $defaults class parameter
|
||||
* TODO: remove support for array in 2.0 as this would currently break backward compatibility
|
||||
*
|
||||
* @param Data|array $defaults
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function setDefaults($defaults)
|
||||
{
|
||||
if (is_array($defaults)) {
|
||||
$this->defaults = new Data($defaults);
|
||||
} elseif ($defaults instanceof Data) {
|
||||
$this->defaults = $defaults;
|
||||
} else {
|
||||
throw new \Exception("Unknown type provided for \$defaults");
|
||||
}
|
||||
}
|
||||
}
|
||||
105
core/lib/composer/vendor/consolidation/config/scenarios/symfony2/src/ConfigInterface.php
vendored
Normal file
105
core/lib/composer/vendor/consolidation/config/scenarios/symfony2/src/ConfigInterface.php
vendored
Normal file
@@ -0,0 +1,105 @@
|
||||
<?php
|
||||
namespace Consolidation\Config;
|
||||
|
||||
interface ConfigInterface
|
||||
{
|
||||
/**
|
||||
* Determine if a non-default config value exists.
|
||||
*/
|
||||
public function has($key);
|
||||
|
||||
/**
|
||||
* Fetch a configuration value
|
||||
*
|
||||
* @param string $key Which config item to look up
|
||||
* @param string|null $defaultFallback Fallback default value to use when
|
||||
* configuration object has neither a value nor a default. Use is
|
||||
* discouraged; use default context in ConfigOverlay, or provide defaults
|
||||
* using a config processor.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function get($key, $defaultFallback = null);
|
||||
|
||||
/**
|
||||
* Set a config value
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function set($key, $value);
|
||||
|
||||
/**
|
||||
* Import configuration from the provided nexted array, replacing whatever
|
||||
* was here previously. No processing is done on the provided data.
|
||||
*
|
||||
* @deprecated Use 'replace'. Dflydev\DotAccessData\Data::import() merges, which is confusing, since this method replaces.
|
||||
*
|
||||
* @param array $data
|
||||
* @return Config
|
||||
*/
|
||||
public function import($data);
|
||||
|
||||
/**
|
||||
* Load configuration from the provided nexted array, replacing whatever
|
||||
* was here previously. No processing is done on the provided data.
|
||||
*
|
||||
* TODO: This will become a required method in version 2.0. Adding now
|
||||
* would break clients that implement ConfigInterface.
|
||||
*
|
||||
* @param array $data
|
||||
* @return Config
|
||||
*/
|
||||
// public function replace($data);
|
||||
|
||||
/**
|
||||
* Import configuration from the provided nexted array, merging with whatever
|
||||
* was here previously. No processing is done on the provided data.
|
||||
* Any data provided to the combine() method will overwrite existing data
|
||||
* with the same key.
|
||||
*
|
||||
* TODO: This will become a required method in version 2.0. Adding now
|
||||
* would break clients that implement ConfigInterface.
|
||||
*
|
||||
* @param array $data
|
||||
* @return Config
|
||||
*/
|
||||
// public function combine($data);
|
||||
|
||||
/**
|
||||
* Export all configuration as a nested array.
|
||||
*/
|
||||
public function export();
|
||||
|
||||
/**
|
||||
* Return the default value for a given configuration item.
|
||||
*
|
||||
* @param string $key
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function hasDefault($key);
|
||||
|
||||
/**
|
||||
* Return the default value for a given configuration item.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $defaultFallback
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getDefault($key, $defaultFallback = null);
|
||||
|
||||
/**
|
||||
* Set the default value for a configuration setting. This allows us to
|
||||
* set defaults either before or after more specific configuration values
|
||||
* are loaded. Keeping defaults separate from current settings also
|
||||
* allows us to determine when a setting has been overridden.
|
||||
*
|
||||
* @param string $key
|
||||
* @param string $value
|
||||
*/
|
||||
public function setDefault($key, $value);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
namespace Consolidation\Config;
|
||||
|
||||
interface GlobalOptionDefaultValuesInterface
|
||||
{
|
||||
/**
|
||||
* Return an associative array of option-key => default-value
|
||||
*/
|
||||
public function getGlobalOptionDefaultValues();
|
||||
}
|
||||
127
core/lib/composer/vendor/consolidation/config/scenarios/symfony2/src/Inject/ConfigForCommand.php
vendored
Normal file
127
core/lib/composer/vendor/consolidation/config/scenarios/symfony2/src/Inject/ConfigForCommand.php
vendored
Normal file
@@ -0,0 +1,127 @@
|
||||
<?php
|
||||
namespace Consolidation\Config\Inject;
|
||||
|
||||
use Consolidation\Config\ConfigInterface;
|
||||
use Consolidation\Config\Util\ConfigFallback;
|
||||
|
||||
use Symfony\Component\Console\ConsoleEvents;
|
||||
use Symfony\Component\Console\Event\ConsoleCommandEvent;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\Console\Application;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
|
||||
class ConfigForCommand implements EventSubscriberInterface
|
||||
{
|
||||
protected $config;
|
||||
protected $application;
|
||||
|
||||
public function __construct(ConfigInterface $config)
|
||||
{
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
public function setApplication(Application $application)
|
||||
{
|
||||
$this->application = $application;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return [ConsoleEvents::COMMAND => 'injectConfiguration'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Before a Console command runs, inject configuration settings
|
||||
* for this command into the default value of the options of
|
||||
* this command.
|
||||
*
|
||||
* @param \Symfony\Component\Console\Event\ConsoleCommandEvent $event
|
||||
*/
|
||||
public function injectConfiguration(ConsoleCommandEvent $event)
|
||||
{
|
||||
$command = $event->getCommand();
|
||||
$this->injectConfigurationForGlobalOptions($event->getInput());
|
||||
$this->injectConfigurationForCommand($command, $event->getInput());
|
||||
|
||||
$targetOfHelpCommand = $this->getHelpCommandTarget($command, $event->getInput());
|
||||
if ($targetOfHelpCommand) {
|
||||
$this->injectConfigurationForCommand($targetOfHelpCommand, $event->getInput());
|
||||
}
|
||||
}
|
||||
|
||||
protected function injectConfigurationForGlobalOptions($input)
|
||||
{
|
||||
if (!$this->application) {
|
||||
return;
|
||||
}
|
||||
|
||||
$configGroup = new ConfigFallback($this->config, 'options');
|
||||
|
||||
$definition = $this->application->getDefinition();
|
||||
$options = $definition->getOptions();
|
||||
|
||||
return $this->injectConfigGroupIntoOptions($configGroup, $options, $input);
|
||||
}
|
||||
|
||||
protected function injectConfigurationForCommand($command, $input)
|
||||
{
|
||||
$commandName = $command->getName();
|
||||
$commandName = str_replace(':', '.', $commandName);
|
||||
$configGroup = new ConfigFallback($this->config, $commandName, 'command.', '.options.');
|
||||
|
||||
$definition = $command->getDefinition();
|
||||
$options = $definition->getOptions();
|
||||
|
||||
return $this->injectConfigGroupIntoOptions($configGroup, $options, $input);
|
||||
}
|
||||
|
||||
protected function injectConfigGroupIntoOptions($configGroup, $options, $input)
|
||||
{
|
||||
foreach ($options as $option => $inputOption) {
|
||||
$key = str_replace('.', '-', $option);
|
||||
$value = $configGroup->get($key);
|
||||
if ($value !== null) {
|
||||
if (is_bool($value) && ($value == true)) {
|
||||
$input->setOption($key, $value);
|
||||
} elseif ($inputOption->acceptValue()) {
|
||||
$inputOption->setDefault($value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function getHelpCommandTarget($command, $input)
|
||||
{
|
||||
if (($command->getName() != 'help') || (!isset($this->application))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->fixInputForSymfony2($command, $input);
|
||||
|
||||
// Symfony Console helpfully swaps 'command_name' and 'command'
|
||||
// depending on whether the user entered `help foo` or `--help foo`.
|
||||
// One of these is always `help`, and the other is the command we
|
||||
// are actually interested in.
|
||||
$nameOfCommandToDescribe = $input->getArgument('command_name');
|
||||
if ($nameOfCommandToDescribe == 'help') {
|
||||
$nameOfCommandToDescribe = $input->getArgument('command');
|
||||
}
|
||||
return $this->application->find($nameOfCommandToDescribe);
|
||||
}
|
||||
|
||||
protected function fixInputForSymfony2($command, $input)
|
||||
{
|
||||
// Symfony 3.x prepares $input for us; Symfony 2.x, on the other
|
||||
// hand, passes it in prior to binding with the command definition,
|
||||
// so we have to go to a little extra work. It may be inadvisable
|
||||
// to do these steps for commands other than 'help'.
|
||||
if (!$input->hasArgument('command_name')) {
|
||||
$command->ignoreValidationErrors();
|
||||
$command->mergeApplicationDefinition();
|
||||
$input->bind($command->getDefinition());
|
||||
}
|
||||
}
|
||||
}
|
||||
47
core/lib/composer/vendor/consolidation/config/scenarios/symfony2/src/Inject/ConfigForSetters.php
vendored
Normal file
47
core/lib/composer/vendor/consolidation/config/scenarios/symfony2/src/Inject/ConfigForSetters.php
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
namespace Consolidation\Config\Inject;
|
||||
|
||||
use Consolidation\Config\Util\ConfigMerge;
|
||||
|
||||
/**
|
||||
* Given an object that contains configuration methods, inject any
|
||||
* configuration found in the configuration file.
|
||||
*
|
||||
* The proper use for this method is to call setter methods of the
|
||||
* provided object. Using configuration to call methods that do work
|
||||
* is an abuse of this mechanism.
|
||||
*/
|
||||
class ConfigForSetters
|
||||
{
|
||||
protected $config;
|
||||
|
||||
public function __construct($config, $group, $prefix = '', $postfix = '')
|
||||
{
|
||||
if (!empty($group) && empty($postfix)) {
|
||||
$postfix = '.';
|
||||
}
|
||||
|
||||
$this->config = new ConfigMerge($config, $group, $prefix, $postfix);
|
||||
}
|
||||
|
||||
public function apply($object, $configurationKey)
|
||||
{
|
||||
$settings = $this->config->get($configurationKey);
|
||||
foreach ($settings as $setterMethod => $args) {
|
||||
$fn = [$object, $setterMethod];
|
||||
if (is_callable($fn)) {
|
||||
$result = call_user_func_array($fn, (array)$args);
|
||||
|
||||
// We require that $fn must only be used with setter methods.
|
||||
// Setter methods are required to always return $this so that
|
||||
// they may be chained. We will therefore throw an exception
|
||||
// for any setter that returns something else.
|
||||
if ($result != $object) {
|
||||
$methodDescription = get_class($object) . "::$setterMethod";
|
||||
$propertyDescription = $this->config->describe($configurationKey);
|
||||
throw new \Exception("$methodDescription did not return '\$this' when processing $propertyDescription.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
35
core/lib/composer/vendor/consolidation/config/scenarios/symfony2/src/Loader/ConfigLoader.php
vendored
Normal file
35
core/lib/composer/vendor/consolidation/config/scenarios/symfony2/src/Loader/ConfigLoader.php
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace Consolidation\Config\Loader;
|
||||
|
||||
/**
|
||||
* Load configuration files.
|
||||
*/
|
||||
abstract class ConfigLoader implements ConfigLoaderInterface
|
||||
{
|
||||
protected $config = [];
|
||||
protected $source = '';
|
||||
|
||||
public function getSourceName()
|
||||
{
|
||||
return $this->source;
|
||||
}
|
||||
|
||||
protected function setSourceName($source)
|
||||
{
|
||||
$this->source = $source;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function export()
|
||||
{
|
||||
return $this->config;
|
||||
}
|
||||
|
||||
public function keys()
|
||||
{
|
||||
return array_keys($this->config);
|
||||
}
|
||||
|
||||
abstract public function load($path);
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Consolidation\Config\Loader;
|
||||
|
||||
/**
|
||||
* Load configuration files, and fill in any property values that
|
||||
* need to be expanded.
|
||||
*/
|
||||
interface ConfigLoaderInterface
|
||||
{
|
||||
/**
|
||||
* Convert loaded configuration into a simple php nested array.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function export();
|
||||
|
||||
/**
|
||||
* Return the top-level keys in the exported data.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function keys();
|
||||
|
||||
/**
|
||||
* Return a symbolic name for this configuration loader instance.
|
||||
*/
|
||||
public function getSourceName();
|
||||
}
|
||||
167
core/lib/composer/vendor/consolidation/config/scenarios/symfony2/src/Loader/ConfigProcessor.php
vendored
Normal file
167
core/lib/composer/vendor/consolidation/config/scenarios/symfony2/src/Loader/ConfigProcessor.php
vendored
Normal file
@@ -0,0 +1,167 @@
|
||||
<?php
|
||||
|
||||
namespace Consolidation\Config\Loader;
|
||||
|
||||
use Grasmash\Expander\Expander;
|
||||
use Consolidation\Config\Util\ArrayUtil;
|
||||
|
||||
/**
|
||||
* The config processor combines multiple configuration
|
||||
* files together, and processes them as necessary.
|
||||
*/
|
||||
class ConfigProcessor
|
||||
{
|
||||
protected $processedConfig = [];
|
||||
protected $unprocessedConfig = [];
|
||||
protected $expander;
|
||||
|
||||
public function __construct($expander = null)
|
||||
{
|
||||
$this->expander = $expander ?: new Expander();
|
||||
}
|
||||
|
||||
/**
|
||||
* Extend the configuration to be processed with the
|
||||
* configuration provided by the specified loader.
|
||||
*
|
||||
* @param ConfigLoaderInterface $loader
|
||||
*/
|
||||
public function extend(ConfigLoaderInterface $loader)
|
||||
{
|
||||
return $this->addFromSource($loader->export(), $loader->getSourceName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Extend the configuration to be processed with
|
||||
* the provided nested array.
|
||||
*
|
||||
* @param array $data
|
||||
*/
|
||||
public function add($data)
|
||||
{
|
||||
$this->unprocessedConfig[] = $data;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extend the configuration to be processed with
|
||||
* the provided nested array. Also record the name
|
||||
* of the data source, if applicable.
|
||||
*
|
||||
* @param array $data
|
||||
* @param string $source
|
||||
*/
|
||||
protected function addFromSource($data, $source = '')
|
||||
{
|
||||
if (empty($source)) {
|
||||
return $this->add($data);
|
||||
}
|
||||
$this->unprocessedConfig[$source] = $data;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process all of the configuration that has been collected,
|
||||
* and return a nested array.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function export($referenceArray = [])
|
||||
{
|
||||
if (!empty($this->unprocessedConfig)) {
|
||||
$this->processedConfig = $this->process(
|
||||
$this->processedConfig,
|
||||
$this->fetchUnprocessed(),
|
||||
$referenceArray
|
||||
);
|
||||
}
|
||||
return $this->processedConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* To aid in debugging: return the source of each configuration item.
|
||||
* n.b. Must call this function *before* export and save the result
|
||||
* if persistence is desired.
|
||||
*/
|
||||
public function sources()
|
||||
{
|
||||
$sources = [];
|
||||
foreach ($this->unprocessedConfig as $sourceName => $config) {
|
||||
if (!empty($sourceName)) {
|
||||
$configSources = ArrayUtil::fillRecursive($config, $sourceName);
|
||||
$sources = ArrayUtil::mergeRecursiveDistinct($sources, $configSources);
|
||||
}
|
||||
}
|
||||
return $sources;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the configuration to be processed, and clear out the
|
||||
* 'unprocessed' list.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function fetchUnprocessed()
|
||||
{
|
||||
$toBeProcessed = $this->unprocessedConfig;
|
||||
$this->unprocessedConfig = [];
|
||||
return $toBeProcessed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use a map-reduce to evaluate the items to be processed,
|
||||
* and merge them into the processed array.
|
||||
*
|
||||
* @param array $processed
|
||||
* @param array $toBeProcessed
|
||||
* @return array
|
||||
*/
|
||||
protected function process(array $processed, array $toBeProcessed, $referenceArray = [])
|
||||
{
|
||||
$toBeReduced = array_map([$this, 'preprocess'], $toBeProcessed);
|
||||
$reduced = array_reduce($toBeReduced, [$this, 'reduceOne'], $processed);
|
||||
return $this->evaluate($reduced, $referenceArray);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a single configuration file from the 'to be processed'
|
||||
* list. By default this is a no-op. Override this method to
|
||||
* provide any desired configuration preprocessing, e.g. dot-notation
|
||||
* expansion of the configuration keys, etc.
|
||||
*
|
||||
* @param array $config
|
||||
* @return array
|
||||
*/
|
||||
protected function preprocess(array $config)
|
||||
{
|
||||
return $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate one item in the 'to be evaluated' list, and then
|
||||
* merge it into the processed configuration (the 'carry').
|
||||
*
|
||||
* @param array $processed
|
||||
* @param array $config
|
||||
* @return array
|
||||
*/
|
||||
protected function reduceOne(array $processed, array $config)
|
||||
{
|
||||
return ArrayUtil::mergeRecursiveDistinct($processed, $config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate one configuration item.
|
||||
*
|
||||
* @param array $processed
|
||||
* @param array $config
|
||||
* @return array
|
||||
*/
|
||||
protected function evaluate(array $config, $referenceArray = [])
|
||||
{
|
||||
return $this->expander->expandArrayProperties(
|
||||
$config,
|
||||
$referenceArray
|
||||
);
|
||||
}
|
||||
}
|
||||
26
core/lib/composer/vendor/consolidation/config/scenarios/symfony2/src/Loader/YamlConfigLoader.php
vendored
Normal file
26
core/lib/composer/vendor/consolidation/config/scenarios/symfony2/src/Loader/YamlConfigLoader.php
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace Consolidation\Config\Loader;
|
||||
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
|
||||
/**
|
||||
* Load configuration files, and fill in any property values that
|
||||
* need to be expanded.
|
||||
*/
|
||||
class YamlConfigLoader extends ConfigLoader
|
||||
{
|
||||
public function load($path)
|
||||
{
|
||||
$this->setSourceName($path);
|
||||
|
||||
// We silently skip any nonexistent config files, so that
|
||||
// clients may simply `load` all of their candidates.
|
||||
if (!file_exists($path)) {
|
||||
$this->config = [];
|
||||
return $this;
|
||||
}
|
||||
$this->config = (array) Yaml::parse(file_get_contents($path));
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
75
core/lib/composer/vendor/consolidation/config/scenarios/symfony2/src/Util/ArrayUtil.php
vendored
Normal file
75
core/lib/composer/vendor/consolidation/config/scenarios/symfony2/src/Util/ArrayUtil.php
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
namespace Consolidation\Config\Util;
|
||||
|
||||
/**
|
||||
* Useful array utilities.
|
||||
*/
|
||||
class ArrayUtil
|
||||
{
|
||||
/**
|
||||
* Merges arrays recursively while preserving.
|
||||
*
|
||||
* @param array $array1
|
||||
* @param array $array2
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @see http://php.net/manual/en/function.array-merge-recursive.php#92195
|
||||
* @see https://github.com/grasmash/bolt/blob/robo-rebase/src/Robo/Common/ArrayManipulator.php#L22
|
||||
*/
|
||||
public static function mergeRecursiveDistinct(
|
||||
array &$array1,
|
||||
array &$array2
|
||||
) {
|
||||
$merged = $array1;
|
||||
foreach ($array2 as $key => &$value) {
|
||||
$merged[$key] = self::mergeRecursiveValue($merged, $key, $value);
|
||||
}
|
||||
return $merged;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the value in an mergeRecursiveDistinct - make a recursive
|
||||
* call if needed.
|
||||
*/
|
||||
protected static function mergeRecursiveValue(&$merged, $key, $value)
|
||||
{
|
||||
if (is_array($value) && isset($merged[$key]) && is_array($merged[$key])) {
|
||||
return self::mergeRecursiveDistinct($merged[$key], $value);
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills all of the leaf-node values of a nested array with the
|
||||
* provided replacement value.
|
||||
*/
|
||||
public static function fillRecursive(array $data, $fill)
|
||||
{
|
||||
$result = [];
|
||||
foreach ($data as $key => $value) {
|
||||
$result[$key] = $fill;
|
||||
if (self::isAssociative($value)) {
|
||||
$result[$key] = self::fillRecursive($value, $fill);
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the provided parameter is an array, and at least
|
||||
* one key is non-numeric.
|
||||
*/
|
||||
public static function isAssociative($testArray)
|
||||
{
|
||||
if (!is_array($testArray)) {
|
||||
return false;
|
||||
}
|
||||
foreach (array_keys($testArray) as $key) {
|
||||
if (!is_numeric($key)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
51
core/lib/composer/vendor/consolidation/config/scenarios/symfony2/src/Util/ConfigFallback.php
vendored
Normal file
51
core/lib/composer/vendor/consolidation/config/scenarios/symfony2/src/Util/ConfigFallback.php
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
namespace Consolidation\Config\Util;
|
||||
|
||||
/**
|
||||
* Fetch a configuration value from a configuration group. If the
|
||||
* desired configuration value is not found in the most specific
|
||||
* group named, keep stepping up to the next parent group until a
|
||||
* value is located.
|
||||
*
|
||||
* Given the following constructor inputs:
|
||||
* - $prefix = "command."
|
||||
* - $group = "foo.bar.baz"
|
||||
* - $postfix = ".options."
|
||||
* Then the `get` method will then consider, in order:
|
||||
* - command.foo.bar.baz.options
|
||||
* - command.foo.bar.options
|
||||
* - command.foo.options
|
||||
* If any of these contain an option for "$key", then return its value.
|
||||
*/
|
||||
class ConfigFallback extends ConfigGroup
|
||||
{
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function get($key)
|
||||
{
|
||||
return $this->getWithFallback($key, $this->group, $this->prefix, $this->postfix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch an option value from a given key, or, if that specific key does
|
||||
* not contain a value, then consult various fallback options until a
|
||||
* value is found.
|
||||
*
|
||||
*/
|
||||
protected function getWithFallback($key, $group, $prefix = '', $postfix = '.')
|
||||
{
|
||||
$configKey = "{$prefix}{$group}${postfix}{$key}";
|
||||
if ($this->config->has($configKey)) {
|
||||
return $this->config->get($configKey);
|
||||
}
|
||||
if ($this->config->hasDefault($configKey)) {
|
||||
return $this->config->getDefault($configKey);
|
||||
}
|
||||
$moreGeneralGroupname = $this->moreGeneralGroupName($group);
|
||||
if ($moreGeneralGroupname) {
|
||||
return $this->getWithFallback($key, $moreGeneralGroupname, $prefix, $postfix);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
61
core/lib/composer/vendor/consolidation/config/scenarios/symfony2/src/Util/ConfigGroup.php
vendored
Normal file
61
core/lib/composer/vendor/consolidation/config/scenarios/symfony2/src/Util/ConfigGroup.php
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
namespace Consolidation\Config\Util;
|
||||
|
||||
/**
|
||||
* Fetch a configuration value from a configuration group. If the
|
||||
* desired configuration value is not found in the most specific
|
||||
* group named, keep stepping up to the next parent group until a
|
||||
* value is located.
|
||||
*
|
||||
* Given the following constructor inputs:
|
||||
* - $prefix = "command."
|
||||
* - $group = "foo.bar.baz"
|
||||
* - $postfix = ".options."
|
||||
* Then the `get` method will then consider, in order:
|
||||
* - command.foo.bar.baz.options
|
||||
* - command.foo.bar.options
|
||||
* - command.foo.options
|
||||
* If any of these contain an option for "$key", then return its value.
|
||||
*/
|
||||
abstract class ConfigGroup
|
||||
{
|
||||
protected $config;
|
||||
protected $group;
|
||||
protected $prefix;
|
||||
protected $postfix;
|
||||
|
||||
public function __construct($config, $group, $prefix = '', $postfix = '.')
|
||||
{
|
||||
$this->config = $config;
|
||||
$this->group = $group;
|
||||
$this->prefix = $prefix;
|
||||
$this->postfix = $postfix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a description of the configuration group (with prefix and postfix).
|
||||
*/
|
||||
public function describe($property)
|
||||
{
|
||||
return $this->prefix . $this->group . $this->postfix . $property;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the requested configuration key from the most specific configuration
|
||||
* group that contains it.
|
||||
*/
|
||||
abstract public function get($key);
|
||||
|
||||
/**
|
||||
* Given a group name, such as "foo.bar.baz", return the next configuration
|
||||
* group in the fallback hierarchy, e.g. "foo.bar".
|
||||
*/
|
||||
protected function moreGeneralGroupName($group)
|
||||
{
|
||||
$result = preg_replace('#\.[^.]*$#', '', $group);
|
||||
if ($result != $group) {
|
||||
return $result;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
34
core/lib/composer/vendor/consolidation/config/scenarios/symfony2/src/Util/ConfigMerge.php
vendored
Normal file
34
core/lib/composer/vendor/consolidation/config/scenarios/symfony2/src/Util/ConfigMerge.php
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
namespace Consolidation\Config\Util;
|
||||
|
||||
/**
|
||||
* Works like 'getWithFallback', but merges results from all applicable
|
||||
* groups. Settings from most specific group take precedence.
|
||||
*/
|
||||
class ConfigMerge extends ConfigGroup
|
||||
{
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function get($key)
|
||||
{
|
||||
return $this->getWithMerge($key, $this->group, $this->prefix, $this->postfix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge available configuration from each configuration group.
|
||||
*/
|
||||
public function getWithMerge($key, $group, $prefix = '', $postfix = '.')
|
||||
{
|
||||
$configKey = "{$prefix}{$group}${postfix}{$key}";
|
||||
$result = $this->config->get($configKey, []);
|
||||
if (!is_array($result)) {
|
||||
throw new \UnexpectedValueException($configKey . ' must be a list of settings to apply.');
|
||||
}
|
||||
$moreGeneralGroupname = $this->moreGeneralGroupName($group);
|
||||
if ($moreGeneralGroupname) {
|
||||
$result += $this->getWithMerge($key, $moreGeneralGroupname, $prefix, $postfix);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
203
core/lib/composer/vendor/consolidation/config/scenarios/symfony2/src/Util/ConfigOverlay.php
vendored
Normal file
203
core/lib/composer/vendor/consolidation/config/scenarios/symfony2/src/Util/ConfigOverlay.php
vendored
Normal file
@@ -0,0 +1,203 @@
|
||||
<?php
|
||||
namespace Consolidation\Config\Util;
|
||||
|
||||
use Consolidation\Config\Config;
|
||||
use Consolidation\Config\ConfigInterface;
|
||||
|
||||
/**
|
||||
* Overlay different configuration objects that implement ConfigInterface
|
||||
* to make a priority-based, merged configuration object.
|
||||
*
|
||||
* Note that using a ConfigOverlay hides the defaults stored in each
|
||||
* individual configuration context. When using overlays, always call
|
||||
* getDefault / setDefault on the ConfigOverlay object itself.
|
||||
*/
|
||||
class ConfigOverlay implements ConfigInterface
|
||||
{
|
||||
protected $contexts = [];
|
||||
|
||||
const DEFAULT_CONTEXT = 'default';
|
||||
const PROCESS_CONTEXT = 'process';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->contexts[self::DEFAULT_CONTEXT] = new Config();
|
||||
$this->contexts[self::PROCESS_CONTEXT] = new Config();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a named configuration object to the configuration overlay.
|
||||
* Configuration objects added LAST have HIGHEST priority, with the
|
||||
* exception of the fact that the process context always has the
|
||||
* highest priority.
|
||||
*
|
||||
* If a context has already been added, its priority will not change.
|
||||
*/
|
||||
public function addContext($name, ConfigInterface $config)
|
||||
{
|
||||
$process = $this->contexts[self::PROCESS_CONTEXT];
|
||||
unset($this->contexts[self::PROCESS_CONTEXT]);
|
||||
$this->contexts[$name] = $config;
|
||||
$this->contexts[self::PROCESS_CONTEXT] = $process;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a placeholder context that will be prioritized higher than
|
||||
* existing contexts. This is done to ensure that contexts added
|
||||
* later will maintain a higher priority if the placeholder context
|
||||
* is later relaced with a different configuration set via addContext().
|
||||
*
|
||||
* @param string $name
|
||||
* @return $this
|
||||
*/
|
||||
public function addPlaceholder($name)
|
||||
{
|
||||
return $this->addContext($name, new Config());
|
||||
}
|
||||
|
||||
/**
|
||||
* Increase the priority of the named context such that it is higher
|
||||
* in priority than any existing context except for the 'process'
|
||||
* context.
|
||||
*
|
||||
* @param string $name
|
||||
* @return $this
|
||||
*/
|
||||
public function increasePriority($name)
|
||||
{
|
||||
$config = $this->getContext($name);
|
||||
unset($this->contexts[$name]);
|
||||
return $this->addContext($name, $config);
|
||||
}
|
||||
|
||||
public function hasContext($name)
|
||||
{
|
||||
return isset($this->contexts[$name]);
|
||||
}
|
||||
|
||||
public function getContext($name)
|
||||
{
|
||||
if ($this->hasContext($name)) {
|
||||
return $this->contexts[$name];
|
||||
}
|
||||
return new Config();
|
||||
}
|
||||
|
||||
public function removeContext($name)
|
||||
{
|
||||
unset($this->contexts[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a non-default config value exists.
|
||||
*/
|
||||
public function findContext($key)
|
||||
{
|
||||
foreach (array_reverse($this->contexts) as $name => $config) {
|
||||
if ($config->has($key)) {
|
||||
return $config;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function has($key)
|
||||
{
|
||||
return $this->findContext($key) != false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function get($key, $default = null)
|
||||
{
|
||||
$context = $this->findContext($key);
|
||||
if ($context) {
|
||||
return $context->get($key, $default);
|
||||
}
|
||||
return $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function set($key, $value)
|
||||
{
|
||||
$this->contexts[self::PROCESS_CONTEXT]->set($key, $value);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function import($data)
|
||||
{
|
||||
$this->unsupported(__FUNCTION__);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function replace($data)
|
||||
{
|
||||
$this->unsupported(__FUNCTION__);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function combine($data)
|
||||
{
|
||||
$this->unsupported(__FUNCTION__);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function unsupported($fn)
|
||||
{
|
||||
throw new \Exception("The method '$fn' is not supported for the ConfigOverlay class.");
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function export()
|
||||
{
|
||||
$export = [];
|
||||
foreach ($this->contexts as $name => $config) {
|
||||
$export = array_merge_recursive($export, $config->export());
|
||||
}
|
||||
return $export;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function hasDefault($key)
|
||||
{
|
||||
return $this->contexts[self::DEFAULT_CONTEXT]->has($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getDefault($key, $default = null)
|
||||
{
|
||||
return $this->contexts[self::DEFAULT_CONTEXT]->get($key, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function setDefault($key, $value)
|
||||
{
|
||||
$this->contexts[self::DEFAULT_CONTEXT]->set($key, $value);
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
96
core/lib/composer/vendor/consolidation/config/scenarios/symfony2/src/Util/EnvConfig.php
vendored
Normal file
96
core/lib/composer/vendor/consolidation/config/scenarios/symfony2/src/Util/EnvConfig.php
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
<?php
|
||||
namespace Consolidation\Config\Util;
|
||||
|
||||
use Consolidation\Config\Config;
|
||||
use Consolidation\Config\ConfigInterface;
|
||||
|
||||
/**
|
||||
* Provide a configuration object that fetches values from environment
|
||||
* variables.
|
||||
*/
|
||||
class EnvConfig implements ConfigInterface
|
||||
{
|
||||
/** @var string */
|
||||
protected $prefix;
|
||||
|
||||
/**
|
||||
* EnvConfig constructor
|
||||
*
|
||||
* @param $prefix The string to appear before every environment
|
||||
* variable key. For example, if the prefix is 'MYAPP_', then
|
||||
* the key 'foo.bar' will be fetched from the environment variable
|
||||
* MYAPP_FOO_BAR.
|
||||
*/
|
||||
public function __construct($prefix)
|
||||
{
|
||||
// Ensure that the prefix is always uppercase, and always
|
||||
// ends with a '_', regardless of the form the caller provided.
|
||||
$this->prefix = strtoupper(rtrim($prefix, '_')) . '_';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function has($key)
|
||||
{
|
||||
return $this->get($key) !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function get($key, $defaultFallback = null)
|
||||
{
|
||||
$envKey = $this->prefix . strtoupper(strtr($key, '.-', '__'));
|
||||
$envKey = str_replace($this->prefix . $this->prefix, $this->prefix, $envKey);
|
||||
return getenv($envKey) ?: $defaultFallback;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function set($key, $value)
|
||||
{
|
||||
throw new \Exception('Cannot call "set" on environmental configuration.');
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function import($data)
|
||||
{
|
||||
// no-op
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function export()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function hasDefault($key)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getDefault($key, $defaultFallback = null)
|
||||
{
|
||||
return $defaultFallback;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function setDefault($key, $value)
|
||||
{
|
||||
throw new \Exception('Cannot call "setDefault" on environmental configuration.');
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
../../tests
|
||||
130
core/lib/composer/vendor/consolidation/config/scenarios/symfony2/tests/ConfigForCommandTest.php
vendored
Normal file
130
core/lib/composer/vendor/consolidation/config/scenarios/symfony2/tests/ConfigForCommandTest.php
vendored
Normal file
@@ -0,0 +1,130 @@
|
||||
<?php
|
||||
namespace Consolidation\Config\Inject;
|
||||
|
||||
use Consolidation\Config\Config;
|
||||
use Consolidation\TestUtils\MyFooCommand;
|
||||
use Symfony\Component\Console\Application;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\ArgvInput;
|
||||
use Symfony\Component\Console\Input\StringInput;
|
||||
use Symfony\Component\Console\Output\BufferedOutput;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
class ConfigForCommandTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
protected $config;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$data = [
|
||||
// Global options
|
||||
'options' => [
|
||||
'global' => 'from-config',
|
||||
],
|
||||
// Define some configuration settings for the options for
|
||||
// the commands my:foo and my:bar.
|
||||
'command' => [
|
||||
'my' => [
|
||||
// commands.my.options.* apply to all my:* commands.
|
||||
'options' => [
|
||||
'dir' => '/etc/common',
|
||||
'priority' => 'normal',
|
||||
],
|
||||
'foo' => [
|
||||
// commands.my.foo.options.* apply only to the my:foo command.
|
||||
'options' => [
|
||||
'name' => 'baz',
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
$this->config = new Config($data);
|
||||
}
|
||||
|
||||
public function testInjection()
|
||||
{
|
||||
$command = new MyFooCommand();
|
||||
$input = new StringInput('my:foo');
|
||||
|
||||
list($status, $output) = $this->runCommandViaApplication($command, $input);
|
||||
|
||||
$expectedOutput = <<< EOT
|
||||
Enter my:foo
|
||||
dir: /etc/common
|
||||
name: baz
|
||||
other: fish
|
||||
EOT;
|
||||
|
||||
$this->assertEquals(0, $status);
|
||||
$this->assertEquals($expectedOutput, $output);
|
||||
}
|
||||
|
||||
public function testInjectionWithOverride()
|
||||
{
|
||||
$command = new MyFooCommand();
|
||||
$input = new StringInput('my:foo --name=Fred');
|
||||
|
||||
list($status, $output) = $this->runCommandViaApplication($command, $input);
|
||||
|
||||
$expectedOutput = <<< EOT
|
||||
Enter my:foo
|
||||
dir: /etc/common
|
||||
name: Fred
|
||||
other: fish
|
||||
EOT;
|
||||
|
||||
$this->assertEquals(0, $status);
|
||||
$this->assertEquals($expectedOutput, $output);
|
||||
}
|
||||
|
||||
public function testHelpDefaultInjection()
|
||||
{
|
||||
$command = new MyFooCommand();
|
||||
$input = new StringInput('help my:foo');
|
||||
|
||||
list($status, $output) = $this->runCommandViaApplication($command, $input);
|
||||
|
||||
$expectedOutput = <<< EOT
|
||||
What is the name of the thing we are naming [default: "baz"]
|
||||
EOT;
|
||||
|
||||
$this->assertEquals(0, $status);
|
||||
$this->assertContains($expectedOutput, $output);
|
||||
|
||||
$expectedOutput = <<< EOT
|
||||
A certain global option. [default: "from-config"]
|
||||
EOT;
|
||||
|
||||
$this->assertContains($expectedOutput, $output);
|
||||
}
|
||||
|
||||
protected function runCommandViaApplication($command, $input)
|
||||
{
|
||||
$application = new Application('TestApplication', '0.0.0');
|
||||
$application->getDefinition()
|
||||
->addOption(
|
||||
new InputOption('--global', null, InputOption::VALUE_REQUIRED, 'A certain global option.', 'hardcoded')
|
||||
);
|
||||
|
||||
$output = new BufferedOutput();
|
||||
|
||||
$configInjector = new ConfigForCommand($this->config);
|
||||
$configInjector->setApplication($application);
|
||||
|
||||
$eventDispatcher = new \Symfony\Component\EventDispatcher\EventDispatcher();
|
||||
$eventDispatcher->addSubscriber($configInjector);
|
||||
$application->setDispatcher($eventDispatcher);
|
||||
|
||||
$application->setAutoExit(false);
|
||||
$application->add($command);
|
||||
|
||||
$statusCode = $application->run($input, $output);
|
||||
$commandOutput = trim($output->fetch());
|
||||
|
||||
return [$statusCode, $commandOutput];
|
||||
}
|
||||
}
|
||||
87
core/lib/composer/vendor/consolidation/config/scenarios/symfony2/tests/ConfigForSettersTest.php
vendored
Normal file
87
core/lib/composer/vendor/consolidation/config/scenarios/symfony2/tests/ConfigForSettersTest.php
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
namespace Consolidation\Config\Inject;
|
||||
|
||||
use Consolidation\Config\Config;
|
||||
use Consolidation\TestUtils\ApplyConfigTestTarget;
|
||||
|
||||
class ConfigForSettersTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testApplyConfig()
|
||||
{
|
||||
$data = [
|
||||
// Define some configuration settings for the configuration
|
||||
// of some task \My\Tasks\Operations\Frobulate.
|
||||
'task' => [
|
||||
'Operations' => [
|
||||
// task.Operations.settings apply to all tasks in
|
||||
// any *.Tass.Operations namespace.
|
||||
'settings' => [
|
||||
'dir' => '/base/dir',
|
||||
],
|
||||
'Frobulate' => [
|
||||
// task.Operations.Frobulate.settings applies only
|
||||
// the Frobulate task.
|
||||
'settings' => [
|
||||
'dir' => '/override/dir',
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
$config = new Config($data);
|
||||
|
||||
$applicator = new ConfigForSetters($config, 'Operations.Frobulate', 'task.');
|
||||
|
||||
$testTarget = new ApplyConfigTestTarget();
|
||||
|
||||
$applicator->apply($testTarget, 'settings');
|
||||
|
||||
$this->assertEquals('/override/dir', $testTarget->getDir());
|
||||
$this->assertEquals(null, $testTarget->getBad());
|
||||
}
|
||||
|
||||
public function testApplyBadConfig()
|
||||
{
|
||||
$data = [
|
||||
// Define some configuration settings for the configuration
|
||||
// of some task \My\Tasks\Operations\Frobulate.
|
||||
'task' => [
|
||||
'Operations' => [
|
||||
// task.Operations.settings apply to all tasks in
|
||||
// any *.Tass.Operations namespace.
|
||||
'settings' => [
|
||||
'dir' => '/base/dir',
|
||||
],
|
||||
'Frobulate' => [
|
||||
// task.Operations.Frobulate.settings applies only
|
||||
// the Frobulate task.
|
||||
'settings' => [
|
||||
'bad' => 'fire truck',
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
$config = new Config($data);
|
||||
|
||||
$applicator = new ConfigForSetters($config, 'Operations.Frobulate', 'task.');
|
||||
|
||||
$testTarget = new ApplyConfigTestTarget();
|
||||
|
||||
$exceptionMessage = '';
|
||||
try
|
||||
{
|
||||
$applicator->apply($testTarget, 'settings');
|
||||
}
|
||||
catch (\Exception $e)
|
||||
{
|
||||
$exceptionMessage = $e->getMessage();
|
||||
}
|
||||
// We would prefer it if bad methods were never called; unfortunately,
|
||||
// declaring the return type of a method cannot be done in a reliable
|
||||
// way (via reflection) until php 7, so we allow these methods to be
|
||||
// called for now.
|
||||
$this->assertEquals('fire truck', $testTarget->getBad());
|
||||
$this->assertEquals('Consolidation\\TestUtils\\ApplyConfigTestTarget::bad did not return \'$this\' when processing task.Operations.Frobulate.settings.', $exceptionMessage);
|
||||
}
|
||||
}
|
||||
91
core/lib/composer/vendor/consolidation/config/scenarios/symfony2/tests/ConfigGroupTest.php
vendored
Normal file
91
core/lib/composer/vendor/consolidation/config/scenarios/symfony2/tests/ConfigGroupTest.php
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
namespace Consolidation\Config\Util;
|
||||
|
||||
use Consolidation\Config\Config;
|
||||
|
||||
class ConfigGroupTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
protected $config;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$data = [
|
||||
// Define some configuration settings for the options for
|
||||
// the commands my:foo and my:bar.
|
||||
'command' => [
|
||||
'my' => [
|
||||
// commands.my.options.* apply to all my:* commands.
|
||||
'options' => [
|
||||
'path' => '/etc/common',
|
||||
'priority' => 'normal',
|
||||
],
|
||||
'foo' => [
|
||||
// commands.my.foo.options.* apply only to the my:foo command.
|
||||
'options' => [
|
||||
'name' => 'baz',
|
||||
],
|
||||
],
|
||||
'bar' => [
|
||||
// Similarly, commands.my.bar.options is for the my:bar command.
|
||||
'options' => [
|
||||
'priority' => 'high',
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
// Define some configuration settings for the configuration
|
||||
// of some task \My\Tasks\Operations\Frobulate.
|
||||
'task' => [
|
||||
'Operations' => [
|
||||
// task.Operations.settings apply to all tasks in
|
||||
// any *.Tass.Operations namespace.
|
||||
'settings' => [
|
||||
'dir' => '/base/dir',
|
||||
],
|
||||
'Frobulate' => [
|
||||
// task.Operations.Frobulate.settings applies only
|
||||
// the Frobulate task.
|
||||
'settings' => [
|
||||
'object' => 'fire truck',
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
$this->config = new Config($data);
|
||||
}
|
||||
|
||||
public function testDotNotation()
|
||||
{
|
||||
// Test the test
|
||||
$this->assertEquals('baz', $this->config->get('command.my.foo.options.name'));
|
||||
}
|
||||
|
||||
public function testFallback()
|
||||
{
|
||||
$fooFallback = new ConfigFallback($this->config, 'my.foo', 'command.', '.options.');
|
||||
$barFallback = new ConfigFallback($this->config, 'my.bar', 'command.', '.options.');
|
||||
|
||||
$this->assertEquals(null, $barFallback->get('name'));
|
||||
$this->assertEquals('baz', $fooFallback->get('name'));
|
||||
$this->assertEquals('high', $barFallback->get('priority'));
|
||||
|
||||
$this->assertEquals('normal', $fooFallback->get('priority'));
|
||||
$this->assertEquals('/etc/common', $barFallback->get('path'));
|
||||
$this->assertEquals('/etc/common', $fooFallback->get('path'));
|
||||
}
|
||||
|
||||
public function testMerge()
|
||||
{
|
||||
$frobulateMerge = new ConfigMerge($this->config, 'Operations.Frobulate', 'task.');
|
||||
|
||||
$settings = $frobulateMerge->get('settings');
|
||||
$this->assertEquals('fire truck', $settings['object']);
|
||||
$this->assertEquals('/base/dir', $settings['dir']);
|
||||
$keys = array_keys($settings);
|
||||
sort($keys);
|
||||
$this->assertEquals('dir,object', implode(',', $keys));
|
||||
}
|
||||
}
|
||||
|
||||
29
core/lib/composer/vendor/consolidation/config/scenarios/symfony2/tests/ConfigLoaderTest.php
vendored
Normal file
29
core/lib/composer/vendor/consolidation/config/scenarios/symfony2/tests/ConfigLoaderTest.php
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
namespace Consolidation\Config\Loader;
|
||||
|
||||
class ConfigLoaderTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testConfigLoader()
|
||||
{
|
||||
$loader = new YamlConfigLoader();
|
||||
|
||||
// Assert that our test data exists (test the test)
|
||||
$path = __DIR__ . '/data/config-1.yml';
|
||||
$this->assertTrue(file_exists($path));
|
||||
|
||||
$loader->load($path);
|
||||
|
||||
$configFile = basename($loader->getSourceName());
|
||||
$this->assertEquals('config-1.yml', $configFile);
|
||||
|
||||
// Make sure that the data we loaded contained the expected keys
|
||||
$keys = $loader->keys();
|
||||
sort($keys);
|
||||
$keysString = implode(',', $keys);
|
||||
$this->assertEquals('c,m', $keysString);
|
||||
|
||||
$configData = $loader->export();
|
||||
$this->assertEquals('foo', $configData['c']);
|
||||
$this->assertEquals('1', $configData['m'][0]);
|
||||
}
|
||||
}
|
||||
168
core/lib/composer/vendor/consolidation/config/scenarios/symfony2/tests/ConfigOverlayTest.php
vendored
Normal file
168
core/lib/composer/vendor/consolidation/config/scenarios/symfony2/tests/ConfigOverlayTest.php
vendored
Normal file
@@ -0,0 +1,168 @@
|
||||
<?php
|
||||
namespace Consolidation\Config\Util;
|
||||
|
||||
use Consolidation\Config\Config;
|
||||
use Consolidation\Config\Loader\ConfigProcessor;
|
||||
use Consolidation\Config\Loader\YamlConfigLoader;
|
||||
|
||||
class ConfigOverlayTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
protected $overlay;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$aliasContext = new Config();
|
||||
$aliasContext->import([
|
||||
'hidden-by-a' => 'alias hidden-by-a',
|
||||
'hidden-by-process' => 'alias hidden-by-process',
|
||||
'options' =>[
|
||||
'a-a' => 'alias-a',
|
||||
],
|
||||
'command' => [
|
||||
'foo' => [
|
||||
'bar' => [
|
||||
'command' => [
|
||||
'options' => [
|
||||
'a-b' => 'alias-b',
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
$configFileContext = new Config();
|
||||
$configFileContext->import([
|
||||
'hidden-by-cf' => 'config-file hidden-by-cf',
|
||||
'hidden-by-a' => 'config-file hidden-by-a',
|
||||
'hidden-by-process' => 'config-file hidden-by-process',
|
||||
'options' =>[
|
||||
'cf-a' => 'config-file-a',
|
||||
],
|
||||
'command' => [
|
||||
'foo' => [
|
||||
'bar' => [
|
||||
'command' => [
|
||||
'options' => [
|
||||
'cf-b' => 'config-file-b',
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
$this->overlay = new ConfigOverlay();
|
||||
$this->overlay->set('hidden-by-process', 'process-h');
|
||||
$this->overlay->addContext('cf', $configFileContext);
|
||||
$this->overlay->addContext('a', $aliasContext);
|
||||
$this->overlay->setDefault('df-a', 'default');
|
||||
$this->overlay->setDefault('hidden-by-a', 'default hidden-by-a');
|
||||
$this->overlay->setDefault('hidden-by-cf', 'default hidden-by-cf');
|
||||
$this->overlay->setDefault('hidden-by-process', 'default hidden-by-process');
|
||||
}
|
||||
|
||||
public function testGetPriority()
|
||||
{
|
||||
$this->assertEquals('process-h', $this->overlay->get('hidden-by-process'));
|
||||
$this->assertEquals('config-file hidden-by-cf', $this->overlay->get('hidden-by-cf'));
|
||||
$this->assertEquals('alias hidden-by-a', $this->overlay->get('hidden-by-a'));
|
||||
}
|
||||
|
||||
public function testDefault()
|
||||
{
|
||||
$this->assertEquals('alias-a', $this->overlay->get('options.a-a'));
|
||||
$this->assertEquals('alias-a', $this->overlay->get('options.a-a', 'ignored'));
|
||||
$this->assertEquals('default', $this->overlay->getDefault('df-a', 'ignored'));
|
||||
$this->assertEquals('nsv', $this->overlay->getDefault('a-a', 'nsv'));
|
||||
|
||||
$this->overlay->setDefault('df-a', 'new value');
|
||||
$this->assertEquals('new value', $this->overlay->getDefault('df-a', 'ignored'));
|
||||
}
|
||||
|
||||
public function testExport()
|
||||
{
|
||||
$data = $this->overlay->export();
|
||||
|
||||
$this->assertEquals('config-file-a', $data['options']['cf-a']);
|
||||
$this->assertEquals('alias-a', $data['options']['a-a']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Exception
|
||||
*/
|
||||
public function testImport()
|
||||
{
|
||||
$data = $this->overlay->import(['a' => 'value']);
|
||||
}
|
||||
|
||||
public function testMaintainPriority()
|
||||
{
|
||||
// Get and re-add the 'cf' context. Its priority should not change.
|
||||
$configFileContext = $this->overlay->getContext('cf');
|
||||
$this->overlay->addContext('cf', $configFileContext);
|
||||
|
||||
// These asserts are the same as in testGetPriority
|
||||
$this->assertEquals('process-h', $this->overlay->get('hidden-by-process'));
|
||||
$this->assertEquals('config-file hidden-by-cf', $this->overlay->get('hidden-by-cf'));
|
||||
$this->assertEquals('alias hidden-by-a', $this->overlay->get('hidden-by-a'));
|
||||
}
|
||||
|
||||
public function testChangePriority()
|
||||
{
|
||||
// Increase the priority of the 'cf' context. Now, it should have a higher
|
||||
// priority than the 'alias' context, but should still have a lower
|
||||
// priority than the 'process' context.
|
||||
$this->overlay->increasePriority('cf');
|
||||
|
||||
// These asserts are the same as in testGetPriority
|
||||
$this->assertEquals('process-h', $this->overlay->get('hidden-by-process'));
|
||||
$this->assertEquals('config-file hidden-by-cf', $this->overlay->get('hidden-by-cf'));
|
||||
|
||||
// This one has changed: the config-file value is now found instead
|
||||
// of the alias value.
|
||||
$this->assertEquals('config-file hidden-by-a', $this->overlay->get('hidden-by-a'));
|
||||
}
|
||||
|
||||
public function testPlaceholder()
|
||||
{
|
||||
$this->overlay->addPlaceholder('lower');
|
||||
|
||||
$higherContext = new Config();
|
||||
$higherContext->import(['priority-test' => 'higher']);
|
||||
|
||||
$lowerContext = new Config();
|
||||
$lowerContext->import(['priority-test' => 'lower']);
|
||||
|
||||
// Usually 'lower' would have the highest priority, since it is
|
||||
// added last. However, our earlier call to 'addPlaceholder' reserves
|
||||
// a spot for it, so the 'higher' context will end up with a higher
|
||||
// priority.
|
||||
$this->overlay->addContext('higher', $higherContext);
|
||||
$this->overlay->addContext('lower', $lowerContext);
|
||||
$this->assertEquals('higher', $this->overlay->get('priority-test', 'neither'));
|
||||
|
||||
// Test to see that we can change the value of the 'higher' context,
|
||||
// and the change will be reflected in the overlay.
|
||||
$higherContext->set('priority-test', 'changed');
|
||||
$this->assertEquals('changed', $this->overlay->get('priority-test', 'neither'));
|
||||
|
||||
// Test to see that the 'process' context still has the highest priority.
|
||||
$this->overlay->set('priority-test', 'process');
|
||||
$higherContext->set('priority-test', 'ignored');
|
||||
$this->assertEquals('process', $this->overlay->get('priority-test', 'neither'));
|
||||
}
|
||||
|
||||
public function testDoesNotHave()
|
||||
{
|
||||
$context = $this->overlay->getContext('no-such-context');
|
||||
$data = $context->export();
|
||||
$this->assertEquals('[]', json_encode($data));
|
||||
|
||||
$this->assertTrue(!$this->overlay->has('no-such-key'));
|
||||
$this->assertTrue(!$this->overlay->hasDefault('no-such-default'));
|
||||
|
||||
$this->assertEquals('no-such-value', $this->overlay->get('no-such-key', 'no-such-value'));
|
||||
|
||||
}
|
||||
}
|
||||
152
core/lib/composer/vendor/consolidation/config/scenarios/symfony2/tests/ConfigProcessorTest.php
vendored
Normal file
152
core/lib/composer/vendor/consolidation/config/scenarios/symfony2/tests/ConfigProcessorTest.php
vendored
Normal file
@@ -0,0 +1,152 @@
|
||||
<?php
|
||||
namespace Consolidation\Config\Loader;
|
||||
|
||||
use Consolidation\TestUtils\TestLoader;
|
||||
|
||||
class ConfigProcessorTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testConfigProcessorAdd()
|
||||
{
|
||||
$config1 = [
|
||||
'c' => 'foo',
|
||||
'm' => [1],
|
||||
];
|
||||
$config2 = [
|
||||
'b' => '${c}bar',
|
||||
'm' => [2],
|
||||
];
|
||||
$config3 = [
|
||||
'a' => '${b}baz',
|
||||
'm' => [3],
|
||||
];
|
||||
|
||||
$processor = new ConfigProcessor();
|
||||
$processor->add($config1);
|
||||
$processor->add($config2);
|
||||
$processor->add($config3);
|
||||
|
||||
$data = $processor->export();
|
||||
$this->assertEquals('foo', $data['c']);
|
||||
$this->assertEquals('foobar', $data['b']);
|
||||
$this->assertEquals('foobarbaz', $data['a']);
|
||||
}
|
||||
|
||||
public function processorForConfigMergeTest($provideSourceNames)
|
||||
{
|
||||
$config1 = [
|
||||
'm' => [
|
||||
'x' => 'x-1',
|
||||
'y' => [
|
||||
'r' => 'r-1',
|
||||
's' => 's-1',
|
||||
't' => 't-1',
|
||||
],
|
||||
'z' => 'z-1',
|
||||
],
|
||||
];
|
||||
$config2 = [
|
||||
'm' => [
|
||||
'w' => 'w-2',
|
||||
'y' => [
|
||||
'q' => 'q-2',
|
||||
's' => 's-2',
|
||||
],
|
||||
'z' => 'z-2',
|
||||
],
|
||||
];
|
||||
$config3 = [
|
||||
'm' => [
|
||||
'v' => 'v-3',
|
||||
'y' => [
|
||||
't' => 't-3',
|
||||
'u' => 'u-3',
|
||||
],
|
||||
'z' => 'z-3',
|
||||
],
|
||||
];
|
||||
|
||||
$processor = new ConfigProcessor();
|
||||
$testLoader = new TestLoader();
|
||||
|
||||
$testLoader->set($config1);
|
||||
$testLoader->setSourceName($provideSourceNames ? 'c-1' : '');
|
||||
$processor->extend($testLoader);
|
||||
|
||||
$testLoader->set($config2);
|
||||
$testLoader->setSourceName($provideSourceNames ? 'c-2' : '');
|
||||
$processor->extend($testLoader);
|
||||
|
||||
$testLoader->set($config3);
|
||||
$testLoader->setSourceName($provideSourceNames ? 'c-3' : '');
|
||||
$processor->extend($testLoader);
|
||||
|
||||
return $processor;
|
||||
}
|
||||
|
||||
public function testConfigProcessorMergeAssociative()
|
||||
{
|
||||
$processor = $this->processorForConfigMergeTest(false);
|
||||
$data = $processor->export();
|
||||
$this->assertEquals('{"m":{"x":"x-1","y":{"r":"r-1","s":"s-2","t":"t-3","q":"q-2","u":"u-3"},"z":"z-3","w":"w-2","v":"v-3"}}', json_encode($data));
|
||||
}
|
||||
|
||||
public function testConfigProcessorMergeAssociativeWithSourceNames()
|
||||
{
|
||||
$processor = $this->processorForConfigMergeTest(true);
|
||||
$sources = $processor->sources();
|
||||
$data = $processor->export();
|
||||
$this->assertEquals('{"m":{"x":"x-1","y":{"r":"r-1","s":"s-2","t":"t-3","q":"q-2","u":"u-3"},"z":"z-3","w":"w-2","v":"v-3"}}', json_encode($data));
|
||||
$this->assertEquals('c-1', $sources['m']['x']);
|
||||
$this->assertEquals('c-1', $sources['m']['y']['r']);
|
||||
$this->assertEquals('c-2', $sources['m']['w']);
|
||||
$this->assertEquals('c-2', $sources['m']['y']['s']);
|
||||
$this->assertEquals('c-3', $sources['m']['z']);
|
||||
$this->assertEquals('c-3', $sources['m']['y']['u']);
|
||||
}
|
||||
|
||||
public function testConfiProcessorSources()
|
||||
{
|
||||
$processor = new ConfigProcessor();
|
||||
$loader = new YamlConfigLoader();
|
||||
$processor->extend($loader->load(__DIR__ . '/data/config-1.yml'));
|
||||
$processor->extend($loader->load(__DIR__ . '/data/config-2.yml'));
|
||||
$processor->extend($loader->load(__DIR__ . '/data/config-3.yml'));
|
||||
|
||||
$sources = $processor->sources();
|
||||
|
||||
$data = $processor->export();
|
||||
$this->assertEquals('foo', $data['c']);
|
||||
$this->assertEquals('foobar', $data['b']);
|
||||
$this->assertEquals('foobarbaz', $data['a']);
|
||||
|
||||
$this->assertEquals('3', $data['m'][0]);
|
||||
|
||||
$this->assertEquals( __DIR__ . '/data/config-3.yml', $sources['a']);
|
||||
$this->assertEquals( __DIR__ . '/data/config-2.yml', $sources['b']);
|
||||
$this->assertEquals( __DIR__ . '/data/config-1.yml', $sources['c']);
|
||||
$this->assertEquals( __DIR__ . '/data/config-3.yml', $sources['m']);
|
||||
}
|
||||
|
||||
public function testConfiProcessorSourcesLoadInReverseOrder()
|
||||
{
|
||||
$processor = new ConfigProcessor();
|
||||
$loader = new YamlConfigLoader();
|
||||
$processor->extend($loader->load(__DIR__ . '/data/config-3.yml'));
|
||||
$processor->extend($loader->load(__DIR__ . '/data/config-2.yml'));
|
||||
$processor->extend($loader->load(__DIR__ . '/data/config-1.yml'));
|
||||
|
||||
$sources = $processor->sources();
|
||||
|
||||
$data = $processor->export();
|
||||
$this->assertEquals('foo', $data['c']);
|
||||
$this->assertEquals('foobar', $data['b']);
|
||||
$this->assertEquals('foobarbaz', $data['a']);
|
||||
|
||||
$this->assertEquals('1', $data['m'][0]);
|
||||
|
||||
$this->assertEquals( __DIR__ . '/data/config-3.yml', $sources['a']);
|
||||
$this->assertEquals( __DIR__ . '/data/config-2.yml', $sources['b']);
|
||||
$this->assertEquals( __DIR__ . '/data/config-1.yml', $sources['c']);
|
||||
$this->assertEquals( __DIR__ . '/data/config-1.yml', $sources['m']);
|
||||
}
|
||||
}
|
||||
140
core/lib/composer/vendor/consolidation/config/scenarios/symfony2/tests/ConfigTest.php
vendored
Normal file
140
core/lib/composer/vendor/consolidation/config/scenarios/symfony2/tests/ConfigTest.php
vendored
Normal file
@@ -0,0 +1,140 @@
|
||||
<?php
|
||||
namespace Consolidation\Config;
|
||||
|
||||
use Consolidation\Config\Loader\ConfigProcessor;
|
||||
use Consolidation\Config\Loader\YamlConfigLoader;
|
||||
|
||||
class ConfigTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testSetters()
|
||||
{
|
||||
// Pointless tests just to ensure everything is covered.
|
||||
$config = new Config();
|
||||
$config->set('foo', 'bar');
|
||||
$data = $config->export();
|
||||
$this->assertEquals('{"foo":"bar"}', json_encode($data));
|
||||
}
|
||||
|
||||
public function testCombine()
|
||||
{
|
||||
// Pointless tests just to ensure everything is covered.
|
||||
$config = new Config();
|
||||
$config->set('foo', 'bar');
|
||||
$config->set('baz', 'boz');
|
||||
$config2 = new Config();
|
||||
$config2->set('foo', 'fu');
|
||||
$config2->set('new', 'blue');
|
||||
$config->combine($config2->export());
|
||||
$this->assertEquals('fu', $config->get('foo'));
|
||||
$this->assertEquals('boz', $config->get('baz'));
|
||||
$this->assertEquals('blue', $config->get('new'));
|
||||
}
|
||||
|
||||
public function testDefault()
|
||||
{
|
||||
$data = [
|
||||
'a' => 'foo',
|
||||
'b' => 'bar',
|
||||
'c' => 'boz',
|
||||
];
|
||||
|
||||
$foo = ["foo" => "bar"];
|
||||
|
||||
$config = new Config($data);
|
||||
|
||||
$config->setDefault('c', 'other');
|
||||
$config->setDefault('d', 'other');
|
||||
$config->setDefault('f', $foo);
|
||||
|
||||
$this->assertEquals('foo', $config->get('a'));
|
||||
$this->assertEquals('boz', $config->get('c'));
|
||||
$this->assertEquals('other', $config->get('d'));
|
||||
$this->assertEquals('other', $config->getDefault('c'));
|
||||
$this->assertEquals('', $config->get('e'));
|
||||
$this->assertEquals('bar', $config->get('f.foo'));
|
||||
$this->assertEquals('{"foo":"bar"}', json_encode($config->get('f')));
|
||||
}
|
||||
|
||||
public function testDefaultsArray()
|
||||
{
|
||||
$data = ['a' => 'foo', 'b' => 'bar', 'c' => 'boz',];
|
||||
$defaults = ['d' => 'foo', 'e' => 'bar', 'f' => 'boz',];
|
||||
|
||||
// Create reflection class to test private methods
|
||||
$configClass = new \ReflectionClass("Consolidation\Config\Config");
|
||||
|
||||
// $defaults
|
||||
$defaultsProperty = $configClass->getProperty("defaults");
|
||||
$defaultsProperty->setAccessible(true);
|
||||
|
||||
// $getDefaults
|
||||
$getDefaultsMethod = $configClass->getMethod("getDefaults");
|
||||
$getDefaultsMethod->setAccessible(true);
|
||||
|
||||
// Test the config class
|
||||
$config = new Config($data);
|
||||
|
||||
// Set $config::defaults to an array to test getter and setter
|
||||
$defaultsProperty->setValue($config, $defaults);
|
||||
$this->assertTrue(is_array($defaultsProperty->getValue($config)));
|
||||
$this->assertInstanceOf('Dflydev\DotAccessData\Data',
|
||||
$getDefaultsMethod->invoke($config));
|
||||
|
||||
// Set $config::defaults to a string to test exception
|
||||
$defaultsProperty->setValue($config, "foo.bar");
|
||||
$this->setExpectedException("Exception");
|
||||
$getDefaultsMethod->invoke($config);
|
||||
}
|
||||
|
||||
public function testConfigurationWithCrossFileReferences()
|
||||
{
|
||||
$config = new Config();
|
||||
$processor = new ConfigProcessor();
|
||||
$loader = new YamlConfigLoader();
|
||||
$processor->extend($loader->load(__DIR__ . '/data/config-1.yml'));
|
||||
$processor->extend($loader->load(__DIR__ . '/data/config-2.yml'));
|
||||
$processor->extend($loader->load(__DIR__ . '/data/config-3.yml'));
|
||||
|
||||
// Does not fail if configuration file cannot be found
|
||||
$processor->extend($loader->load(__DIR__ . '/data/no-such-file.yml'));
|
||||
|
||||
// We must capture the sources before exporting, as export
|
||||
// dumps this information.
|
||||
$sources = $processor->sources();
|
||||
|
||||
$config->import($processor->export());
|
||||
|
||||
$this->assertEquals(implode(',', $config->get('m')), '3');
|
||||
$this->assertEquals($config->get('a'), 'foobarbaz');
|
||||
|
||||
$this->assertEquals($sources['a'], __DIR__ . '/data/config-3.yml');
|
||||
$this->assertEquals($sources['b'], __DIR__ . '/data/config-2.yml');
|
||||
$this->assertEquals($sources['c'], __DIR__ . '/data/config-1.yml');
|
||||
}
|
||||
|
||||
public function testConfigurationWithReverseOrderCrossFileReferences()
|
||||
{
|
||||
$config = new Config();
|
||||
$processor = new ConfigProcessor();
|
||||
$loader = new YamlConfigLoader();
|
||||
$processor->extend($loader->load(__DIR__ . '/data/config-3.yml'));
|
||||
$processor->extend($loader->load(__DIR__ . '/data/config-2.yml'));
|
||||
$processor->extend($loader->load(__DIR__ . '/data/config-1.yml'));
|
||||
|
||||
$sources = $processor->sources();
|
||||
$config->import($processor->export());
|
||||
|
||||
$this->assertEquals(implode(',', $config->get('m')), '1');
|
||||
|
||||
if (strpos($config->get('a'), '$') !== false) {
|
||||
throw new \PHPUnit_Framework_SkippedTestError(
|
||||
'Evaluation of cross-file references in reverse order not supported.'
|
||||
);
|
||||
}
|
||||
$this->assertEquals($config->get('a'), 'foobarbaz');
|
||||
|
||||
$this->assertEquals($sources['a'], __DIR__ . '/data/config-3.yml');
|
||||
$this->assertEquals($sources['b'], __DIR__ . '/data/config-2.yml');
|
||||
$this->assertEquals($sources['c'], __DIR__ . '/data/config-1.yml');
|
||||
}
|
||||
}
|
||||
3
core/lib/composer/vendor/consolidation/config/scenarios/symfony2/tests/data/config-1.yml
vendored
Normal file
3
core/lib/composer/vendor/consolidation/config/scenarios/symfony2/tests/data/config-1.yml
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
c: foo
|
||||
m:
|
||||
- 1
|
||||
3
core/lib/composer/vendor/consolidation/config/scenarios/symfony2/tests/data/config-2.yml
vendored
Normal file
3
core/lib/composer/vendor/consolidation/config/scenarios/symfony2/tests/data/config-2.yml
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
b: ${c}bar
|
||||
m:
|
||||
- 2
|
||||
3
core/lib/composer/vendor/consolidation/config/scenarios/symfony2/tests/data/config-3.yml
vendored
Normal file
3
core/lib/composer/vendor/consolidation/config/scenarios/symfony2/tests/data/config-3.yml
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
a: ${b}baz
|
||||
m:
|
||||
- 3
|
||||
23
core/lib/composer/vendor/consolidation/config/scenarios/symfony2/tests/scripts/install-scenario
vendored
Executable file
23
core/lib/composer/vendor/consolidation/config/scenarios/symfony2/tests/scripts/install-scenario
vendored
Executable file
@@ -0,0 +1,23 @@
|
||||
#!/bin/bash
|
||||
|
||||
SCENARIO=$1
|
||||
ACTION=${2-install}
|
||||
|
||||
dir=dependencies/${SCENARIO}
|
||||
if [ -z "$SCENARIO" ] ; then
|
||||
SCENARIO=default
|
||||
dir=.
|
||||
fi
|
||||
|
||||
|
||||
if [ ! -d "$dir" ] ; then
|
||||
echo "Requested scenario '${SCENARIO}' does not exist."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Switch to ${SCENARIO} scenario"
|
||||
|
||||
set -ex
|
||||
|
||||
composer -n --working-dir=$dir ${ACTION} --prefer-dist --no-scripts
|
||||
composer -n --working-dir=$dir info
|
||||
66
core/lib/composer/vendor/consolidation/config/scenarios/symfony2/tests/scripts/prep-dependencies
vendored
Executable file
66
core/lib/composer/vendor/consolidation/config/scenarios/symfony2/tests/scripts/prep-dependencies
vendored
Executable file
@@ -0,0 +1,66 @@
|
||||
#!/bin/bash
|
||||
|
||||
#
|
||||
# This script is called automatically on every `composer update`.
|
||||
# See "post-update-cmd" in the "scripts" section of composer.json.
|
||||
#
|
||||
# This script will create a derived composer.json / composer.lock
|
||||
# pair for every test scenario. Test scenarios are defined in the
|
||||
# "scenarios" file, which should be customized to suit the needs
|
||||
# of the project.
|
||||
#
|
||||
|
||||
SELF_DIRNAME="`dirname -- "$0"`"
|
||||
source ${SELF_DIRNAME}/scenarios
|
||||
|
||||
echo
|
||||
echo "::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::"
|
||||
echo "::"
|
||||
echo ":: Update dependencies for the following scenarios:"
|
||||
echo "::"
|
||||
echo ":: ${SCENARIOS}"
|
||||
echo "::"
|
||||
echo "::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::"
|
||||
echo
|
||||
|
||||
set -ex
|
||||
|
||||
for SCENARIO in ${SCENARIOS} ; do
|
||||
|
||||
dir=dependencies/${SCENARIO}
|
||||
|
||||
# Define indirect variable names
|
||||
stability_variable="stability_${SCENARIO}"
|
||||
requirement_variable="requirement_${SCENARIO}"
|
||||
platform_php_variable="platform_php_${SCENARIO}"
|
||||
|
||||
echo "### Create $dir/composer.json for ${SCENARIO} scenario"
|
||||
mkdir -p $dir
|
||||
cp composer.json $dir
|
||||
|
||||
# Then set our own platform php version if applicable (otherwise unset it)
|
||||
composer -n --working-dir=$dir config platform.php "${!platform_php_variable---unset}"
|
||||
|
||||
# Temporarily set our vendor directory to 'vendor'
|
||||
composer -n --working-dir=$dir config vendor-dir vendor
|
||||
|
||||
# Set an appropriate minimum stability for this version of Symfony
|
||||
composer -n --working-dir=$dir config minimum-stability "${!stability_variable-stable}"
|
||||
|
||||
# Add a constraint to limit the Symfony version
|
||||
composer -n --working-dir=$dir require --dev --no-update "${!requirement_variable}"
|
||||
|
||||
# Create the composer.lock file. Ignore the vendor directory created.
|
||||
composer -n --working-dir=$dir update --no-scripts
|
||||
|
||||
# Set the vendor directory to its final desired location.
|
||||
composer -n --working-dir=$dir config vendor-dir '../../vendor'
|
||||
|
||||
# The 'autoload' section specifies directory paths that are relative
|
||||
# to the composer.json file. We will drop in some symlinks so that
|
||||
# these paths will resolve as if the composer.json were in the root.
|
||||
for target in $AUTOLOAD_DIRECTORIES ; do
|
||||
ln -s -f ../../$target $dir
|
||||
done
|
||||
|
||||
done
|
||||
12
core/lib/composer/vendor/consolidation/config/scenarios/symfony2/tests/scripts/scenarios
vendored
Executable file
12
core/lib/composer/vendor/consolidation/config/scenarios/symfony2/tests/scripts/scenarios
vendored
Executable file
@@ -0,0 +1,12 @@
|
||||
#!/bin/bash
|
||||
|
||||
SCENARIOS="symfony2 symfony3 symfony4"
|
||||
|
||||
AUTOLOAD_DIRECTORIES='src tests'
|
||||
|
||||
platform_php_symfony2='5.4'
|
||||
platform_php_symfony3='5.6'
|
||||
|
||||
requirement_symfony2='symfony/console:^2.8'
|
||||
requirement_symfony3='symfony/console:^3'
|
||||
requirement_symfony4='symfony/console:^4'
|
||||
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace Consolidation\TestUtils;
|
||||
|
||||
class ApplyConfigTestTarget
|
||||
{
|
||||
protected $dir;
|
||||
protected $value;
|
||||
|
||||
/**
|
||||
* A proper setter for the 'dir' property
|
||||
*/
|
||||
public function dir($dir)
|
||||
{
|
||||
$this->dir = $dir;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* A getter for the 'dir' property that we will use to
|
||||
* determine if the setter was called.
|
||||
*/
|
||||
public function getDir()
|
||||
{
|
||||
return $this->dir;
|
||||
}
|
||||
|
||||
/**
|
||||
* A bad setter that does not return $this.
|
||||
*/
|
||||
public function bad($value)
|
||||
{
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* A getter for the bad setter.
|
||||
*/
|
||||
public function getBad()
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
}
|
||||
47
core/lib/composer/vendor/consolidation/config/scenarios/symfony2/tests/src/MyFooCommand.php
vendored
Normal file
47
core/lib/composer/vendor/consolidation/config/scenarios/symfony2/tests/src/MyFooCommand.php
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
namespace Consolidation\TestUtils;
|
||||
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
|
||||
class MyFooCommand extends Command
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
->setName('my:foo')
|
||||
->setDescription('My foo command.')
|
||||
->setHelp('This command tests command option injection by echoing its options')
|
||||
->addOption(
|
||||
'other',
|
||||
null,
|
||||
InputOption::VALUE_REQUIRED,
|
||||
'Some other option',
|
||||
'fish'
|
||||
)
|
||||
->addOption(
|
||||
'name',
|
||||
null,
|
||||
InputOption::VALUE_REQUIRED,
|
||||
'What is the name of the thing we are naming',
|
||||
'George'
|
||||
)
|
||||
->addOption(
|
||||
'dir',
|
||||
null,
|
||||
InputOption::VALUE_REQUIRED,
|
||||
'What is the base directory to use for this command',
|
||||
'/default/path'
|
||||
);
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$output->writeln('Enter my:foo');
|
||||
$output->writeln('dir: ' . $input->getOption('dir'));
|
||||
$output->writeln('name: ' . $input->getOption('name'));
|
||||
$output->writeln('other: ' . $input->getOption('other'));
|
||||
}
|
||||
}
|
||||
36
core/lib/composer/vendor/consolidation/config/scenarios/symfony2/tests/src/TestLoader.php
vendored
Normal file
36
core/lib/composer/vendor/consolidation/config/scenarios/symfony2/tests/src/TestLoader.php
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace Consolidation\TestUtils;
|
||||
|
||||
use Consolidation\Config\Loader\ConfigLoaderInterface;
|
||||
|
||||
class TestLoader implements ConfigLoaderInterface
|
||||
{
|
||||
protected $data;
|
||||
protected $sourceName;
|
||||
|
||||
public function set($data)
|
||||
{
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
public function setSourceName($name)
|
||||
{
|
||||
$this->sourceName = $name;
|
||||
}
|
||||
|
||||
public function export()
|
||||
{
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
public function keys()
|
||||
{
|
||||
return array_keys($this->data);
|
||||
}
|
||||
|
||||
public function getSourceName()
|
||||
{
|
||||
return $this->sourceName;
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
../../src
|
||||
157
core/lib/composer/vendor/consolidation/config/scenarios/symfony4/src/Config.php
vendored
Normal file
157
core/lib/composer/vendor/consolidation/config/scenarios/symfony4/src/Config.php
vendored
Normal file
@@ -0,0 +1,157 @@
|
||||
<?php
|
||||
|
||||
namespace Consolidation\Config;
|
||||
|
||||
use Dflydev\DotAccessData\Data;
|
||||
|
||||
class Config implements ConfigInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @var Data
|
||||
*/
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* TODO: make this private in 2.0 to prevent being saved as an array
|
||||
* Making private now breaks backward compatibility
|
||||
*
|
||||
* @var Data
|
||||
*/
|
||||
protected $defaults;
|
||||
|
||||
/**
|
||||
* Create a new configuration object, and initialize it with
|
||||
* the provided nested array containing configuration data.
|
||||
*
|
||||
* @param array $data - Config data to store
|
||||
*/
|
||||
public function __construct(array $data = null)
|
||||
{
|
||||
$this->config = new Data($data);
|
||||
$this->setDefaults(new Data());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function has($key)
|
||||
{
|
||||
return ($this->config->has($key));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function get($key, $defaultFallback = null)
|
||||
{
|
||||
if ($this->has($key)) {
|
||||
return $this->config->get($key);
|
||||
}
|
||||
return $this->getDefault($key, $defaultFallback);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function set($key, $value)
|
||||
{
|
||||
$this->config->set($key, $value);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function import($data)
|
||||
{
|
||||
return $this->replace($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function replace($data)
|
||||
{
|
||||
$this->config = new Data($data);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function combine($data)
|
||||
{
|
||||
if (!empty($data)) {
|
||||
$this->config->import($data, true);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function export()
|
||||
{
|
||||
return $this->config->export();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function hasDefault($key)
|
||||
{
|
||||
return $this->getDefaults()->has($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDefault($key, $defaultFallback = null)
|
||||
{
|
||||
return $this->hasDefault($key) ? $this->getDefaults()->get($key) : $defaultFallback;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setDefault($key, $value)
|
||||
{
|
||||
$this->getDefaults()->set($key, $value);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the class $defaults property and ensure it's a Data object
|
||||
* TODO: remove Data object validation in 2.0
|
||||
*
|
||||
* @return Data
|
||||
*/
|
||||
protected function getDefaults()
|
||||
{
|
||||
// Ensure $this->defaults is a Data object (not an array)
|
||||
if (!$this->defaults instanceof Data) {
|
||||
$this->setDefaults($this->defaults);
|
||||
}
|
||||
return $this->defaults;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the $defaults class parameter
|
||||
* TODO: remove support for array in 2.0 as this would currently break backward compatibility
|
||||
*
|
||||
* @param Data|array $defaults
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function setDefaults($defaults)
|
||||
{
|
||||
if (is_array($defaults)) {
|
||||
$this->defaults = new Data($defaults);
|
||||
} elseif ($defaults instanceof Data) {
|
||||
$this->defaults = $defaults;
|
||||
} else {
|
||||
throw new \Exception("Unknown type provided for \$defaults");
|
||||
}
|
||||
}
|
||||
}
|
||||
105
core/lib/composer/vendor/consolidation/config/scenarios/symfony4/src/ConfigInterface.php
vendored
Normal file
105
core/lib/composer/vendor/consolidation/config/scenarios/symfony4/src/ConfigInterface.php
vendored
Normal file
@@ -0,0 +1,105 @@
|
||||
<?php
|
||||
namespace Consolidation\Config;
|
||||
|
||||
interface ConfigInterface
|
||||
{
|
||||
/**
|
||||
* Determine if a non-default config value exists.
|
||||
*/
|
||||
public function has($key);
|
||||
|
||||
/**
|
||||
* Fetch a configuration value
|
||||
*
|
||||
* @param string $key Which config item to look up
|
||||
* @param string|null $defaultFallback Fallback default value to use when
|
||||
* configuration object has neither a value nor a default. Use is
|
||||
* discouraged; use default context in ConfigOverlay, or provide defaults
|
||||
* using a config processor.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function get($key, $defaultFallback = null);
|
||||
|
||||
/**
|
||||
* Set a config value
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function set($key, $value);
|
||||
|
||||
/**
|
||||
* Import configuration from the provided nexted array, replacing whatever
|
||||
* was here previously. No processing is done on the provided data.
|
||||
*
|
||||
* @deprecated Use 'replace'. Dflydev\DotAccessData\Data::import() merges, which is confusing, since this method replaces.
|
||||
*
|
||||
* @param array $data
|
||||
* @return Config
|
||||
*/
|
||||
public function import($data);
|
||||
|
||||
/**
|
||||
* Load configuration from the provided nexted array, replacing whatever
|
||||
* was here previously. No processing is done on the provided data.
|
||||
*
|
||||
* TODO: This will become a required method in version 2.0. Adding now
|
||||
* would break clients that implement ConfigInterface.
|
||||
*
|
||||
* @param array $data
|
||||
* @return Config
|
||||
*/
|
||||
// public function replace($data);
|
||||
|
||||
/**
|
||||
* Import configuration from the provided nexted array, merging with whatever
|
||||
* was here previously. No processing is done on the provided data.
|
||||
* Any data provided to the combine() method will overwrite existing data
|
||||
* with the same key.
|
||||
*
|
||||
* TODO: This will become a required method in version 2.0. Adding now
|
||||
* would break clients that implement ConfigInterface.
|
||||
*
|
||||
* @param array $data
|
||||
* @return Config
|
||||
*/
|
||||
// public function combine($data);
|
||||
|
||||
/**
|
||||
* Export all configuration as a nested array.
|
||||
*/
|
||||
public function export();
|
||||
|
||||
/**
|
||||
* Return the default value for a given configuration item.
|
||||
*
|
||||
* @param string $key
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function hasDefault($key);
|
||||
|
||||
/**
|
||||
* Return the default value for a given configuration item.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $defaultFallback
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getDefault($key, $defaultFallback = null);
|
||||
|
||||
/**
|
||||
* Set the default value for a configuration setting. This allows us to
|
||||
* set defaults either before or after more specific configuration values
|
||||
* are loaded. Keeping defaults separate from current settings also
|
||||
* allows us to determine when a setting has been overridden.
|
||||
*
|
||||
* @param string $key
|
||||
* @param string $value
|
||||
*/
|
||||
public function setDefault($key, $value);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
namespace Consolidation\Config;
|
||||
|
||||
interface GlobalOptionDefaultValuesInterface
|
||||
{
|
||||
/**
|
||||
* Return an associative array of option-key => default-value
|
||||
*/
|
||||
public function getGlobalOptionDefaultValues();
|
||||
}
|
||||
127
core/lib/composer/vendor/consolidation/config/scenarios/symfony4/src/Inject/ConfigForCommand.php
vendored
Normal file
127
core/lib/composer/vendor/consolidation/config/scenarios/symfony4/src/Inject/ConfigForCommand.php
vendored
Normal file
@@ -0,0 +1,127 @@
|
||||
<?php
|
||||
namespace Consolidation\Config\Inject;
|
||||
|
||||
use Consolidation\Config\ConfigInterface;
|
||||
use Consolidation\Config\Util\ConfigFallback;
|
||||
|
||||
use Symfony\Component\Console\ConsoleEvents;
|
||||
use Symfony\Component\Console\Event\ConsoleCommandEvent;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\Console\Application;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
|
||||
class ConfigForCommand implements EventSubscriberInterface
|
||||
{
|
||||
protected $config;
|
||||
protected $application;
|
||||
|
||||
public function __construct(ConfigInterface $config)
|
||||
{
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
public function setApplication(Application $application)
|
||||
{
|
||||
$this->application = $application;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return [ConsoleEvents::COMMAND => 'injectConfiguration'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Before a Console command runs, inject configuration settings
|
||||
* for this command into the default value of the options of
|
||||
* this command.
|
||||
*
|
||||
* @param \Symfony\Component\Console\Event\ConsoleCommandEvent $event
|
||||
*/
|
||||
public function injectConfiguration(ConsoleCommandEvent $event)
|
||||
{
|
||||
$command = $event->getCommand();
|
||||
$this->injectConfigurationForGlobalOptions($event->getInput());
|
||||
$this->injectConfigurationForCommand($command, $event->getInput());
|
||||
|
||||
$targetOfHelpCommand = $this->getHelpCommandTarget($command, $event->getInput());
|
||||
if ($targetOfHelpCommand) {
|
||||
$this->injectConfigurationForCommand($targetOfHelpCommand, $event->getInput());
|
||||
}
|
||||
}
|
||||
|
||||
protected function injectConfigurationForGlobalOptions($input)
|
||||
{
|
||||
if (!$this->application) {
|
||||
return;
|
||||
}
|
||||
|
||||
$configGroup = new ConfigFallback($this->config, 'options');
|
||||
|
||||
$definition = $this->application->getDefinition();
|
||||
$options = $definition->getOptions();
|
||||
|
||||
return $this->injectConfigGroupIntoOptions($configGroup, $options, $input);
|
||||
}
|
||||
|
||||
protected function injectConfigurationForCommand($command, $input)
|
||||
{
|
||||
$commandName = $command->getName();
|
||||
$commandName = str_replace(':', '.', $commandName);
|
||||
$configGroup = new ConfigFallback($this->config, $commandName, 'command.', '.options.');
|
||||
|
||||
$definition = $command->getDefinition();
|
||||
$options = $definition->getOptions();
|
||||
|
||||
return $this->injectConfigGroupIntoOptions($configGroup, $options, $input);
|
||||
}
|
||||
|
||||
protected function injectConfigGroupIntoOptions($configGroup, $options, $input)
|
||||
{
|
||||
foreach ($options as $option => $inputOption) {
|
||||
$key = str_replace('.', '-', $option);
|
||||
$value = $configGroup->get($key);
|
||||
if ($value !== null) {
|
||||
if (is_bool($value) && ($value == true)) {
|
||||
$input->setOption($key, $value);
|
||||
} elseif ($inputOption->acceptValue()) {
|
||||
$inputOption->setDefault($value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function getHelpCommandTarget($command, $input)
|
||||
{
|
||||
if (($command->getName() != 'help') || (!isset($this->application))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->fixInputForSymfony2($command, $input);
|
||||
|
||||
// Symfony Console helpfully swaps 'command_name' and 'command'
|
||||
// depending on whether the user entered `help foo` or `--help foo`.
|
||||
// One of these is always `help`, and the other is the command we
|
||||
// are actually interested in.
|
||||
$nameOfCommandToDescribe = $input->getArgument('command_name');
|
||||
if ($nameOfCommandToDescribe == 'help') {
|
||||
$nameOfCommandToDescribe = $input->getArgument('command');
|
||||
}
|
||||
return $this->application->find($nameOfCommandToDescribe);
|
||||
}
|
||||
|
||||
protected function fixInputForSymfony2($command, $input)
|
||||
{
|
||||
// Symfony 3.x prepares $input for us; Symfony 2.x, on the other
|
||||
// hand, passes it in prior to binding with the command definition,
|
||||
// so we have to go to a little extra work. It may be inadvisable
|
||||
// to do these steps for commands other than 'help'.
|
||||
if (!$input->hasArgument('command_name')) {
|
||||
$command->ignoreValidationErrors();
|
||||
$command->mergeApplicationDefinition();
|
||||
$input->bind($command->getDefinition());
|
||||
}
|
||||
}
|
||||
}
|
||||
47
core/lib/composer/vendor/consolidation/config/scenarios/symfony4/src/Inject/ConfigForSetters.php
vendored
Normal file
47
core/lib/composer/vendor/consolidation/config/scenarios/symfony4/src/Inject/ConfigForSetters.php
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
namespace Consolidation\Config\Inject;
|
||||
|
||||
use Consolidation\Config\Util\ConfigMerge;
|
||||
|
||||
/**
|
||||
* Given an object that contains configuration methods, inject any
|
||||
* configuration found in the configuration file.
|
||||
*
|
||||
* The proper use for this method is to call setter methods of the
|
||||
* provided object. Using configuration to call methods that do work
|
||||
* is an abuse of this mechanism.
|
||||
*/
|
||||
class ConfigForSetters
|
||||
{
|
||||
protected $config;
|
||||
|
||||
public function __construct($config, $group, $prefix = '', $postfix = '')
|
||||
{
|
||||
if (!empty($group) && empty($postfix)) {
|
||||
$postfix = '.';
|
||||
}
|
||||
|
||||
$this->config = new ConfigMerge($config, $group, $prefix, $postfix);
|
||||
}
|
||||
|
||||
public function apply($object, $configurationKey)
|
||||
{
|
||||
$settings = $this->config->get($configurationKey);
|
||||
foreach ($settings as $setterMethod => $args) {
|
||||
$fn = [$object, $setterMethod];
|
||||
if (is_callable($fn)) {
|
||||
$result = call_user_func_array($fn, (array)$args);
|
||||
|
||||
// We require that $fn must only be used with setter methods.
|
||||
// Setter methods are required to always return $this so that
|
||||
// they may be chained. We will therefore throw an exception
|
||||
// for any setter that returns something else.
|
||||
if ($result != $object) {
|
||||
$methodDescription = get_class($object) . "::$setterMethod";
|
||||
$propertyDescription = $this->config->describe($configurationKey);
|
||||
throw new \Exception("$methodDescription did not return '\$this' when processing $propertyDescription.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
35
core/lib/composer/vendor/consolidation/config/scenarios/symfony4/src/Loader/ConfigLoader.php
vendored
Normal file
35
core/lib/composer/vendor/consolidation/config/scenarios/symfony4/src/Loader/ConfigLoader.php
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace Consolidation\Config\Loader;
|
||||
|
||||
/**
|
||||
* Load configuration files.
|
||||
*/
|
||||
abstract class ConfigLoader implements ConfigLoaderInterface
|
||||
{
|
||||
protected $config = [];
|
||||
protected $source = '';
|
||||
|
||||
public function getSourceName()
|
||||
{
|
||||
return $this->source;
|
||||
}
|
||||
|
||||
protected function setSourceName($source)
|
||||
{
|
||||
$this->source = $source;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function export()
|
||||
{
|
||||
return $this->config;
|
||||
}
|
||||
|
||||
public function keys()
|
||||
{
|
||||
return array_keys($this->config);
|
||||
}
|
||||
|
||||
abstract public function load($path);
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Consolidation\Config\Loader;
|
||||
|
||||
/**
|
||||
* Load configuration files, and fill in any property values that
|
||||
* need to be expanded.
|
||||
*/
|
||||
interface ConfigLoaderInterface
|
||||
{
|
||||
/**
|
||||
* Convert loaded configuration into a simple php nested array.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function export();
|
||||
|
||||
/**
|
||||
* Return the top-level keys in the exported data.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function keys();
|
||||
|
||||
/**
|
||||
* Return a symbolic name for this configuration loader instance.
|
||||
*/
|
||||
public function getSourceName();
|
||||
}
|
||||
167
core/lib/composer/vendor/consolidation/config/scenarios/symfony4/src/Loader/ConfigProcessor.php
vendored
Normal file
167
core/lib/composer/vendor/consolidation/config/scenarios/symfony4/src/Loader/ConfigProcessor.php
vendored
Normal file
@@ -0,0 +1,167 @@
|
||||
<?php
|
||||
|
||||
namespace Consolidation\Config\Loader;
|
||||
|
||||
use Grasmash\Expander\Expander;
|
||||
use Consolidation\Config\Util\ArrayUtil;
|
||||
|
||||
/**
|
||||
* The config processor combines multiple configuration
|
||||
* files together, and processes them as necessary.
|
||||
*/
|
||||
class ConfigProcessor
|
||||
{
|
||||
protected $processedConfig = [];
|
||||
protected $unprocessedConfig = [];
|
||||
protected $expander;
|
||||
|
||||
public function __construct($expander = null)
|
||||
{
|
||||
$this->expander = $expander ?: new Expander();
|
||||
}
|
||||
|
||||
/**
|
||||
* Extend the configuration to be processed with the
|
||||
* configuration provided by the specified loader.
|
||||
*
|
||||
* @param ConfigLoaderInterface $loader
|
||||
*/
|
||||
public function extend(ConfigLoaderInterface $loader)
|
||||
{
|
||||
return $this->addFromSource($loader->export(), $loader->getSourceName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Extend the configuration to be processed with
|
||||
* the provided nested array.
|
||||
*
|
||||
* @param array $data
|
||||
*/
|
||||
public function add($data)
|
||||
{
|
||||
$this->unprocessedConfig[] = $data;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extend the configuration to be processed with
|
||||
* the provided nested array. Also record the name
|
||||
* of the data source, if applicable.
|
||||
*
|
||||
* @param array $data
|
||||
* @param string $source
|
||||
*/
|
||||
protected function addFromSource($data, $source = '')
|
||||
{
|
||||
if (empty($source)) {
|
||||
return $this->add($data);
|
||||
}
|
||||
$this->unprocessedConfig[$source] = $data;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process all of the configuration that has been collected,
|
||||
* and return a nested array.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function export($referenceArray = [])
|
||||
{
|
||||
if (!empty($this->unprocessedConfig)) {
|
||||
$this->processedConfig = $this->process(
|
||||
$this->processedConfig,
|
||||
$this->fetchUnprocessed(),
|
||||
$referenceArray
|
||||
);
|
||||
}
|
||||
return $this->processedConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* To aid in debugging: return the source of each configuration item.
|
||||
* n.b. Must call this function *before* export and save the result
|
||||
* if persistence is desired.
|
||||
*/
|
||||
public function sources()
|
||||
{
|
||||
$sources = [];
|
||||
foreach ($this->unprocessedConfig as $sourceName => $config) {
|
||||
if (!empty($sourceName)) {
|
||||
$configSources = ArrayUtil::fillRecursive($config, $sourceName);
|
||||
$sources = ArrayUtil::mergeRecursiveDistinct($sources, $configSources);
|
||||
}
|
||||
}
|
||||
return $sources;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the configuration to be processed, and clear out the
|
||||
* 'unprocessed' list.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function fetchUnprocessed()
|
||||
{
|
||||
$toBeProcessed = $this->unprocessedConfig;
|
||||
$this->unprocessedConfig = [];
|
||||
return $toBeProcessed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use a map-reduce to evaluate the items to be processed,
|
||||
* and merge them into the processed array.
|
||||
*
|
||||
* @param array $processed
|
||||
* @param array $toBeProcessed
|
||||
* @return array
|
||||
*/
|
||||
protected function process(array $processed, array $toBeProcessed, $referenceArray = [])
|
||||
{
|
||||
$toBeReduced = array_map([$this, 'preprocess'], $toBeProcessed);
|
||||
$reduced = array_reduce($toBeReduced, [$this, 'reduceOne'], $processed);
|
||||
return $this->evaluate($reduced, $referenceArray);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a single configuration file from the 'to be processed'
|
||||
* list. By default this is a no-op. Override this method to
|
||||
* provide any desired configuration preprocessing, e.g. dot-notation
|
||||
* expansion of the configuration keys, etc.
|
||||
*
|
||||
* @param array $config
|
||||
* @return array
|
||||
*/
|
||||
protected function preprocess(array $config)
|
||||
{
|
||||
return $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate one item in the 'to be evaluated' list, and then
|
||||
* merge it into the processed configuration (the 'carry').
|
||||
*
|
||||
* @param array $processed
|
||||
* @param array $config
|
||||
* @return array
|
||||
*/
|
||||
protected function reduceOne(array $processed, array $config)
|
||||
{
|
||||
return ArrayUtil::mergeRecursiveDistinct($processed, $config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate one configuration item.
|
||||
*
|
||||
* @param array $processed
|
||||
* @param array $config
|
||||
* @return array
|
||||
*/
|
||||
protected function evaluate(array $config, $referenceArray = [])
|
||||
{
|
||||
return $this->expander->expandArrayProperties(
|
||||
$config,
|
||||
$referenceArray
|
||||
);
|
||||
}
|
||||
}
|
||||
26
core/lib/composer/vendor/consolidation/config/scenarios/symfony4/src/Loader/YamlConfigLoader.php
vendored
Normal file
26
core/lib/composer/vendor/consolidation/config/scenarios/symfony4/src/Loader/YamlConfigLoader.php
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace Consolidation\Config\Loader;
|
||||
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
|
||||
/**
|
||||
* Load configuration files, and fill in any property values that
|
||||
* need to be expanded.
|
||||
*/
|
||||
class YamlConfigLoader extends ConfigLoader
|
||||
{
|
||||
public function load($path)
|
||||
{
|
||||
$this->setSourceName($path);
|
||||
|
||||
// We silently skip any nonexistent config files, so that
|
||||
// clients may simply `load` all of their candidates.
|
||||
if (!file_exists($path)) {
|
||||
$this->config = [];
|
||||
return $this;
|
||||
}
|
||||
$this->config = (array) Yaml::parse(file_get_contents($path));
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
75
core/lib/composer/vendor/consolidation/config/scenarios/symfony4/src/Util/ArrayUtil.php
vendored
Normal file
75
core/lib/composer/vendor/consolidation/config/scenarios/symfony4/src/Util/ArrayUtil.php
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
namespace Consolidation\Config\Util;
|
||||
|
||||
/**
|
||||
* Useful array utilities.
|
||||
*/
|
||||
class ArrayUtil
|
||||
{
|
||||
/**
|
||||
* Merges arrays recursively while preserving.
|
||||
*
|
||||
* @param array $array1
|
||||
* @param array $array2
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @see http://php.net/manual/en/function.array-merge-recursive.php#92195
|
||||
* @see https://github.com/grasmash/bolt/blob/robo-rebase/src/Robo/Common/ArrayManipulator.php#L22
|
||||
*/
|
||||
public static function mergeRecursiveDistinct(
|
||||
array &$array1,
|
||||
array &$array2
|
||||
) {
|
||||
$merged = $array1;
|
||||
foreach ($array2 as $key => &$value) {
|
||||
$merged[$key] = self::mergeRecursiveValue($merged, $key, $value);
|
||||
}
|
||||
return $merged;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the value in an mergeRecursiveDistinct - make a recursive
|
||||
* call if needed.
|
||||
*/
|
||||
protected static function mergeRecursiveValue(&$merged, $key, $value)
|
||||
{
|
||||
if (is_array($value) && isset($merged[$key]) && is_array($merged[$key])) {
|
||||
return self::mergeRecursiveDistinct($merged[$key], $value);
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills all of the leaf-node values of a nested array with the
|
||||
* provided replacement value.
|
||||
*/
|
||||
public static function fillRecursive(array $data, $fill)
|
||||
{
|
||||
$result = [];
|
||||
foreach ($data as $key => $value) {
|
||||
$result[$key] = $fill;
|
||||
if (self::isAssociative($value)) {
|
||||
$result[$key] = self::fillRecursive($value, $fill);
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the provided parameter is an array, and at least
|
||||
* one key is non-numeric.
|
||||
*/
|
||||
public static function isAssociative($testArray)
|
||||
{
|
||||
if (!is_array($testArray)) {
|
||||
return false;
|
||||
}
|
||||
foreach (array_keys($testArray) as $key) {
|
||||
if (!is_numeric($key)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
51
core/lib/composer/vendor/consolidation/config/scenarios/symfony4/src/Util/ConfigFallback.php
vendored
Normal file
51
core/lib/composer/vendor/consolidation/config/scenarios/symfony4/src/Util/ConfigFallback.php
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
namespace Consolidation\Config\Util;
|
||||
|
||||
/**
|
||||
* Fetch a configuration value from a configuration group. If the
|
||||
* desired configuration value is not found in the most specific
|
||||
* group named, keep stepping up to the next parent group until a
|
||||
* value is located.
|
||||
*
|
||||
* Given the following constructor inputs:
|
||||
* - $prefix = "command."
|
||||
* - $group = "foo.bar.baz"
|
||||
* - $postfix = ".options."
|
||||
* Then the `get` method will then consider, in order:
|
||||
* - command.foo.bar.baz.options
|
||||
* - command.foo.bar.options
|
||||
* - command.foo.options
|
||||
* If any of these contain an option for "$key", then return its value.
|
||||
*/
|
||||
class ConfigFallback extends ConfigGroup
|
||||
{
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function get($key)
|
||||
{
|
||||
return $this->getWithFallback($key, $this->group, $this->prefix, $this->postfix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch an option value from a given key, or, if that specific key does
|
||||
* not contain a value, then consult various fallback options until a
|
||||
* value is found.
|
||||
*
|
||||
*/
|
||||
protected function getWithFallback($key, $group, $prefix = '', $postfix = '.')
|
||||
{
|
||||
$configKey = "{$prefix}{$group}${postfix}{$key}";
|
||||
if ($this->config->has($configKey)) {
|
||||
return $this->config->get($configKey);
|
||||
}
|
||||
if ($this->config->hasDefault($configKey)) {
|
||||
return $this->config->getDefault($configKey);
|
||||
}
|
||||
$moreGeneralGroupname = $this->moreGeneralGroupName($group);
|
||||
if ($moreGeneralGroupname) {
|
||||
return $this->getWithFallback($key, $moreGeneralGroupname, $prefix, $postfix);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
61
core/lib/composer/vendor/consolidation/config/scenarios/symfony4/src/Util/ConfigGroup.php
vendored
Normal file
61
core/lib/composer/vendor/consolidation/config/scenarios/symfony4/src/Util/ConfigGroup.php
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
namespace Consolidation\Config\Util;
|
||||
|
||||
/**
|
||||
* Fetch a configuration value from a configuration group. If the
|
||||
* desired configuration value is not found in the most specific
|
||||
* group named, keep stepping up to the next parent group until a
|
||||
* value is located.
|
||||
*
|
||||
* Given the following constructor inputs:
|
||||
* - $prefix = "command."
|
||||
* - $group = "foo.bar.baz"
|
||||
* - $postfix = ".options."
|
||||
* Then the `get` method will then consider, in order:
|
||||
* - command.foo.bar.baz.options
|
||||
* - command.foo.bar.options
|
||||
* - command.foo.options
|
||||
* If any of these contain an option for "$key", then return its value.
|
||||
*/
|
||||
abstract class ConfigGroup
|
||||
{
|
||||
protected $config;
|
||||
protected $group;
|
||||
protected $prefix;
|
||||
protected $postfix;
|
||||
|
||||
public function __construct($config, $group, $prefix = '', $postfix = '.')
|
||||
{
|
||||
$this->config = $config;
|
||||
$this->group = $group;
|
||||
$this->prefix = $prefix;
|
||||
$this->postfix = $postfix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a description of the configuration group (with prefix and postfix).
|
||||
*/
|
||||
public function describe($property)
|
||||
{
|
||||
return $this->prefix . $this->group . $this->postfix . $property;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the requested configuration key from the most specific configuration
|
||||
* group that contains it.
|
||||
*/
|
||||
abstract public function get($key);
|
||||
|
||||
/**
|
||||
* Given a group name, such as "foo.bar.baz", return the next configuration
|
||||
* group in the fallback hierarchy, e.g. "foo.bar".
|
||||
*/
|
||||
protected function moreGeneralGroupName($group)
|
||||
{
|
||||
$result = preg_replace('#\.[^.]*$#', '', $group);
|
||||
if ($result != $group) {
|
||||
return $result;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
34
core/lib/composer/vendor/consolidation/config/scenarios/symfony4/src/Util/ConfigMerge.php
vendored
Normal file
34
core/lib/composer/vendor/consolidation/config/scenarios/symfony4/src/Util/ConfigMerge.php
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
namespace Consolidation\Config\Util;
|
||||
|
||||
/**
|
||||
* Works like 'getWithFallback', but merges results from all applicable
|
||||
* groups. Settings from most specific group take precedence.
|
||||
*/
|
||||
class ConfigMerge extends ConfigGroup
|
||||
{
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function get($key)
|
||||
{
|
||||
return $this->getWithMerge($key, $this->group, $this->prefix, $this->postfix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge available configuration from each configuration group.
|
||||
*/
|
||||
public function getWithMerge($key, $group, $prefix = '', $postfix = '.')
|
||||
{
|
||||
$configKey = "{$prefix}{$group}${postfix}{$key}";
|
||||
$result = $this->config->get($configKey, []);
|
||||
if (!is_array($result)) {
|
||||
throw new \UnexpectedValueException($configKey . ' must be a list of settings to apply.');
|
||||
}
|
||||
$moreGeneralGroupname = $this->moreGeneralGroupName($group);
|
||||
if ($moreGeneralGroupname) {
|
||||
$result += $this->getWithMerge($key, $moreGeneralGroupname, $prefix, $postfix);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
203
core/lib/composer/vendor/consolidation/config/scenarios/symfony4/src/Util/ConfigOverlay.php
vendored
Normal file
203
core/lib/composer/vendor/consolidation/config/scenarios/symfony4/src/Util/ConfigOverlay.php
vendored
Normal file
@@ -0,0 +1,203 @@
|
||||
<?php
|
||||
namespace Consolidation\Config\Util;
|
||||
|
||||
use Consolidation\Config\Config;
|
||||
use Consolidation\Config\ConfigInterface;
|
||||
|
||||
/**
|
||||
* Overlay different configuration objects that implement ConfigInterface
|
||||
* to make a priority-based, merged configuration object.
|
||||
*
|
||||
* Note that using a ConfigOverlay hides the defaults stored in each
|
||||
* individual configuration context. When using overlays, always call
|
||||
* getDefault / setDefault on the ConfigOverlay object itself.
|
||||
*/
|
||||
class ConfigOverlay implements ConfigInterface
|
||||
{
|
||||
protected $contexts = [];
|
||||
|
||||
const DEFAULT_CONTEXT = 'default';
|
||||
const PROCESS_CONTEXT = 'process';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->contexts[self::DEFAULT_CONTEXT] = new Config();
|
||||
$this->contexts[self::PROCESS_CONTEXT] = new Config();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a named configuration object to the configuration overlay.
|
||||
* Configuration objects added LAST have HIGHEST priority, with the
|
||||
* exception of the fact that the process context always has the
|
||||
* highest priority.
|
||||
*
|
||||
* If a context has already been added, its priority will not change.
|
||||
*/
|
||||
public function addContext($name, ConfigInterface $config)
|
||||
{
|
||||
$process = $this->contexts[self::PROCESS_CONTEXT];
|
||||
unset($this->contexts[self::PROCESS_CONTEXT]);
|
||||
$this->contexts[$name] = $config;
|
||||
$this->contexts[self::PROCESS_CONTEXT] = $process;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a placeholder context that will be prioritized higher than
|
||||
* existing contexts. This is done to ensure that contexts added
|
||||
* later will maintain a higher priority if the placeholder context
|
||||
* is later relaced with a different configuration set via addContext().
|
||||
*
|
||||
* @param string $name
|
||||
* @return $this
|
||||
*/
|
||||
public function addPlaceholder($name)
|
||||
{
|
||||
return $this->addContext($name, new Config());
|
||||
}
|
||||
|
||||
/**
|
||||
* Increase the priority of the named context such that it is higher
|
||||
* in priority than any existing context except for the 'process'
|
||||
* context.
|
||||
*
|
||||
* @param string $name
|
||||
* @return $this
|
||||
*/
|
||||
public function increasePriority($name)
|
||||
{
|
||||
$config = $this->getContext($name);
|
||||
unset($this->contexts[$name]);
|
||||
return $this->addContext($name, $config);
|
||||
}
|
||||
|
||||
public function hasContext($name)
|
||||
{
|
||||
return isset($this->contexts[$name]);
|
||||
}
|
||||
|
||||
public function getContext($name)
|
||||
{
|
||||
if ($this->hasContext($name)) {
|
||||
return $this->contexts[$name];
|
||||
}
|
||||
return new Config();
|
||||
}
|
||||
|
||||
public function removeContext($name)
|
||||
{
|
||||
unset($this->contexts[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a non-default config value exists.
|
||||
*/
|
||||
public function findContext($key)
|
||||
{
|
||||
foreach (array_reverse($this->contexts) as $name => $config) {
|
||||
if ($config->has($key)) {
|
||||
return $config;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function has($key)
|
||||
{
|
||||
return $this->findContext($key) != false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function get($key, $default = null)
|
||||
{
|
||||
$context = $this->findContext($key);
|
||||
if ($context) {
|
||||
return $context->get($key, $default);
|
||||
}
|
||||
return $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function set($key, $value)
|
||||
{
|
||||
$this->contexts[self::PROCESS_CONTEXT]->set($key, $value);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function import($data)
|
||||
{
|
||||
$this->unsupported(__FUNCTION__);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function replace($data)
|
||||
{
|
||||
$this->unsupported(__FUNCTION__);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function combine($data)
|
||||
{
|
||||
$this->unsupported(__FUNCTION__);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function unsupported($fn)
|
||||
{
|
||||
throw new \Exception("The method '$fn' is not supported for the ConfigOverlay class.");
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function export()
|
||||
{
|
||||
$export = [];
|
||||
foreach ($this->contexts as $name => $config) {
|
||||
$export = array_merge_recursive($export, $config->export());
|
||||
}
|
||||
return $export;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function hasDefault($key)
|
||||
{
|
||||
return $this->contexts[self::DEFAULT_CONTEXT]->has($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getDefault($key, $default = null)
|
||||
{
|
||||
return $this->contexts[self::DEFAULT_CONTEXT]->get($key, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function setDefault($key, $value)
|
||||
{
|
||||
$this->contexts[self::DEFAULT_CONTEXT]->set($key, $value);
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
96
core/lib/composer/vendor/consolidation/config/scenarios/symfony4/src/Util/EnvConfig.php
vendored
Normal file
96
core/lib/composer/vendor/consolidation/config/scenarios/symfony4/src/Util/EnvConfig.php
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
<?php
|
||||
namespace Consolidation\Config\Util;
|
||||
|
||||
use Consolidation\Config\Config;
|
||||
use Consolidation\Config\ConfigInterface;
|
||||
|
||||
/**
|
||||
* Provide a configuration object that fetches values from environment
|
||||
* variables.
|
||||
*/
|
||||
class EnvConfig implements ConfigInterface
|
||||
{
|
||||
/** @var string */
|
||||
protected $prefix;
|
||||
|
||||
/**
|
||||
* EnvConfig constructor
|
||||
*
|
||||
* @param $prefix The string to appear before every environment
|
||||
* variable key. For example, if the prefix is 'MYAPP_', then
|
||||
* the key 'foo.bar' will be fetched from the environment variable
|
||||
* MYAPP_FOO_BAR.
|
||||
*/
|
||||
public function __construct($prefix)
|
||||
{
|
||||
// Ensure that the prefix is always uppercase, and always
|
||||
// ends with a '_', regardless of the form the caller provided.
|
||||
$this->prefix = strtoupper(rtrim($prefix, '_')) . '_';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function has($key)
|
||||
{
|
||||
return $this->get($key) !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function get($key, $defaultFallback = null)
|
||||
{
|
||||
$envKey = $this->prefix . strtoupper(strtr($key, '.-', '__'));
|
||||
$envKey = str_replace($this->prefix . $this->prefix, $this->prefix, $envKey);
|
||||
return getenv($envKey) ?: $defaultFallback;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function set($key, $value)
|
||||
{
|
||||
throw new \Exception('Cannot call "set" on environmental configuration.');
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function import($data)
|
||||
{
|
||||
// no-op
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function export()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function hasDefault($key)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getDefault($key, $defaultFallback = null)
|
||||
{
|
||||
return $defaultFallback;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function setDefault($key, $value)
|
||||
{
|
||||
throw new \Exception('Cannot call "setDefault" on environmental configuration.');
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
../../tests
|
||||
130
core/lib/composer/vendor/consolidation/config/scenarios/symfony4/tests/ConfigForCommandTest.php
vendored
Normal file
130
core/lib/composer/vendor/consolidation/config/scenarios/symfony4/tests/ConfigForCommandTest.php
vendored
Normal file
@@ -0,0 +1,130 @@
|
||||
<?php
|
||||
namespace Consolidation\Config\Inject;
|
||||
|
||||
use Consolidation\Config\Config;
|
||||
use Consolidation\TestUtils\MyFooCommand;
|
||||
use Symfony\Component\Console\Application;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\ArgvInput;
|
||||
use Symfony\Component\Console\Input\StringInput;
|
||||
use Symfony\Component\Console\Output\BufferedOutput;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
class ConfigForCommandTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
protected $config;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$data = [
|
||||
// Global options
|
||||
'options' => [
|
||||
'global' => 'from-config',
|
||||
],
|
||||
// Define some configuration settings for the options for
|
||||
// the commands my:foo and my:bar.
|
||||
'command' => [
|
||||
'my' => [
|
||||
// commands.my.options.* apply to all my:* commands.
|
||||
'options' => [
|
||||
'dir' => '/etc/common',
|
||||
'priority' => 'normal',
|
||||
],
|
||||
'foo' => [
|
||||
// commands.my.foo.options.* apply only to the my:foo command.
|
||||
'options' => [
|
||||
'name' => 'baz',
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
$this->config = new Config($data);
|
||||
}
|
||||
|
||||
public function testInjection()
|
||||
{
|
||||
$command = new MyFooCommand();
|
||||
$input = new StringInput('my:foo');
|
||||
|
||||
list($status, $output) = $this->runCommandViaApplication($command, $input);
|
||||
|
||||
$expectedOutput = <<< EOT
|
||||
Enter my:foo
|
||||
dir: /etc/common
|
||||
name: baz
|
||||
other: fish
|
||||
EOT;
|
||||
|
||||
$this->assertEquals(0, $status);
|
||||
$this->assertEquals($expectedOutput, $output);
|
||||
}
|
||||
|
||||
public function testInjectionWithOverride()
|
||||
{
|
||||
$command = new MyFooCommand();
|
||||
$input = new StringInput('my:foo --name=Fred');
|
||||
|
||||
list($status, $output) = $this->runCommandViaApplication($command, $input);
|
||||
|
||||
$expectedOutput = <<< EOT
|
||||
Enter my:foo
|
||||
dir: /etc/common
|
||||
name: Fred
|
||||
other: fish
|
||||
EOT;
|
||||
|
||||
$this->assertEquals(0, $status);
|
||||
$this->assertEquals($expectedOutput, $output);
|
||||
}
|
||||
|
||||
public function testHelpDefaultInjection()
|
||||
{
|
||||
$command = new MyFooCommand();
|
||||
$input = new StringInput('help my:foo');
|
||||
|
||||
list($status, $output) = $this->runCommandViaApplication($command, $input);
|
||||
|
||||
$expectedOutput = <<< EOT
|
||||
What is the name of the thing we are naming [default: "baz"]
|
||||
EOT;
|
||||
|
||||
$this->assertEquals(0, $status);
|
||||
$this->assertContains($expectedOutput, $output);
|
||||
|
||||
$expectedOutput = <<< EOT
|
||||
A certain global option. [default: "from-config"]
|
||||
EOT;
|
||||
|
||||
$this->assertContains($expectedOutput, $output);
|
||||
}
|
||||
|
||||
protected function runCommandViaApplication($command, $input)
|
||||
{
|
||||
$application = new Application('TestApplication', '0.0.0');
|
||||
$application->getDefinition()
|
||||
->addOption(
|
||||
new InputOption('--global', null, InputOption::VALUE_REQUIRED, 'A certain global option.', 'hardcoded')
|
||||
);
|
||||
|
||||
$output = new BufferedOutput();
|
||||
|
||||
$configInjector = new ConfigForCommand($this->config);
|
||||
$configInjector->setApplication($application);
|
||||
|
||||
$eventDispatcher = new \Symfony\Component\EventDispatcher\EventDispatcher();
|
||||
$eventDispatcher->addSubscriber($configInjector);
|
||||
$application->setDispatcher($eventDispatcher);
|
||||
|
||||
$application->setAutoExit(false);
|
||||
$application->add($command);
|
||||
|
||||
$statusCode = $application->run($input, $output);
|
||||
$commandOutput = trim($output->fetch());
|
||||
|
||||
return [$statusCode, $commandOutput];
|
||||
}
|
||||
}
|
||||
87
core/lib/composer/vendor/consolidation/config/scenarios/symfony4/tests/ConfigForSettersTest.php
vendored
Normal file
87
core/lib/composer/vendor/consolidation/config/scenarios/symfony4/tests/ConfigForSettersTest.php
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
namespace Consolidation\Config\Inject;
|
||||
|
||||
use Consolidation\Config\Config;
|
||||
use Consolidation\TestUtils\ApplyConfigTestTarget;
|
||||
|
||||
class ConfigForSettersTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testApplyConfig()
|
||||
{
|
||||
$data = [
|
||||
// Define some configuration settings for the configuration
|
||||
// of some task \My\Tasks\Operations\Frobulate.
|
||||
'task' => [
|
||||
'Operations' => [
|
||||
// task.Operations.settings apply to all tasks in
|
||||
// any *.Tass.Operations namespace.
|
||||
'settings' => [
|
||||
'dir' => '/base/dir',
|
||||
],
|
||||
'Frobulate' => [
|
||||
// task.Operations.Frobulate.settings applies only
|
||||
// the Frobulate task.
|
||||
'settings' => [
|
||||
'dir' => '/override/dir',
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
$config = new Config($data);
|
||||
|
||||
$applicator = new ConfigForSetters($config, 'Operations.Frobulate', 'task.');
|
||||
|
||||
$testTarget = new ApplyConfigTestTarget();
|
||||
|
||||
$applicator->apply($testTarget, 'settings');
|
||||
|
||||
$this->assertEquals('/override/dir', $testTarget->getDir());
|
||||
$this->assertEquals(null, $testTarget->getBad());
|
||||
}
|
||||
|
||||
public function testApplyBadConfig()
|
||||
{
|
||||
$data = [
|
||||
// Define some configuration settings for the configuration
|
||||
// of some task \My\Tasks\Operations\Frobulate.
|
||||
'task' => [
|
||||
'Operations' => [
|
||||
// task.Operations.settings apply to all tasks in
|
||||
// any *.Tass.Operations namespace.
|
||||
'settings' => [
|
||||
'dir' => '/base/dir',
|
||||
],
|
||||
'Frobulate' => [
|
||||
// task.Operations.Frobulate.settings applies only
|
||||
// the Frobulate task.
|
||||
'settings' => [
|
||||
'bad' => 'fire truck',
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
$config = new Config($data);
|
||||
|
||||
$applicator = new ConfigForSetters($config, 'Operations.Frobulate', 'task.');
|
||||
|
||||
$testTarget = new ApplyConfigTestTarget();
|
||||
|
||||
$exceptionMessage = '';
|
||||
try
|
||||
{
|
||||
$applicator->apply($testTarget, 'settings');
|
||||
}
|
||||
catch (\Exception $e)
|
||||
{
|
||||
$exceptionMessage = $e->getMessage();
|
||||
}
|
||||
// We would prefer it if bad methods were never called; unfortunately,
|
||||
// declaring the return type of a method cannot be done in a reliable
|
||||
// way (via reflection) until php 7, so we allow these methods to be
|
||||
// called for now.
|
||||
$this->assertEquals('fire truck', $testTarget->getBad());
|
||||
$this->assertEquals('Consolidation\\TestUtils\\ApplyConfigTestTarget::bad did not return \'$this\' when processing task.Operations.Frobulate.settings.', $exceptionMessage);
|
||||
}
|
||||
}
|
||||
91
core/lib/composer/vendor/consolidation/config/scenarios/symfony4/tests/ConfigGroupTest.php
vendored
Normal file
91
core/lib/composer/vendor/consolidation/config/scenarios/symfony4/tests/ConfigGroupTest.php
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
namespace Consolidation\Config\Util;
|
||||
|
||||
use Consolidation\Config\Config;
|
||||
|
||||
class ConfigGroupTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
protected $config;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$data = [
|
||||
// Define some configuration settings for the options for
|
||||
// the commands my:foo and my:bar.
|
||||
'command' => [
|
||||
'my' => [
|
||||
// commands.my.options.* apply to all my:* commands.
|
||||
'options' => [
|
||||
'path' => '/etc/common',
|
||||
'priority' => 'normal',
|
||||
],
|
||||
'foo' => [
|
||||
// commands.my.foo.options.* apply only to the my:foo command.
|
||||
'options' => [
|
||||
'name' => 'baz',
|
||||
],
|
||||
],
|
||||
'bar' => [
|
||||
// Similarly, commands.my.bar.options is for the my:bar command.
|
||||
'options' => [
|
||||
'priority' => 'high',
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
// Define some configuration settings for the configuration
|
||||
// of some task \My\Tasks\Operations\Frobulate.
|
||||
'task' => [
|
||||
'Operations' => [
|
||||
// task.Operations.settings apply to all tasks in
|
||||
// any *.Tass.Operations namespace.
|
||||
'settings' => [
|
||||
'dir' => '/base/dir',
|
||||
],
|
||||
'Frobulate' => [
|
||||
// task.Operations.Frobulate.settings applies only
|
||||
// the Frobulate task.
|
||||
'settings' => [
|
||||
'object' => 'fire truck',
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
$this->config = new Config($data);
|
||||
}
|
||||
|
||||
public function testDotNotation()
|
||||
{
|
||||
// Test the test
|
||||
$this->assertEquals('baz', $this->config->get('command.my.foo.options.name'));
|
||||
}
|
||||
|
||||
public function testFallback()
|
||||
{
|
||||
$fooFallback = new ConfigFallback($this->config, 'my.foo', 'command.', '.options.');
|
||||
$barFallback = new ConfigFallback($this->config, 'my.bar', 'command.', '.options.');
|
||||
|
||||
$this->assertEquals(null, $barFallback->get('name'));
|
||||
$this->assertEquals('baz', $fooFallback->get('name'));
|
||||
$this->assertEquals('high', $barFallback->get('priority'));
|
||||
|
||||
$this->assertEquals('normal', $fooFallback->get('priority'));
|
||||
$this->assertEquals('/etc/common', $barFallback->get('path'));
|
||||
$this->assertEquals('/etc/common', $fooFallback->get('path'));
|
||||
}
|
||||
|
||||
public function testMerge()
|
||||
{
|
||||
$frobulateMerge = new ConfigMerge($this->config, 'Operations.Frobulate', 'task.');
|
||||
|
||||
$settings = $frobulateMerge->get('settings');
|
||||
$this->assertEquals('fire truck', $settings['object']);
|
||||
$this->assertEquals('/base/dir', $settings['dir']);
|
||||
$keys = array_keys($settings);
|
||||
sort($keys);
|
||||
$this->assertEquals('dir,object', implode(',', $keys));
|
||||
}
|
||||
}
|
||||
|
||||
29
core/lib/composer/vendor/consolidation/config/scenarios/symfony4/tests/ConfigLoaderTest.php
vendored
Normal file
29
core/lib/composer/vendor/consolidation/config/scenarios/symfony4/tests/ConfigLoaderTest.php
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
namespace Consolidation\Config\Loader;
|
||||
|
||||
class ConfigLoaderTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testConfigLoader()
|
||||
{
|
||||
$loader = new YamlConfigLoader();
|
||||
|
||||
// Assert that our test data exists (test the test)
|
||||
$path = __DIR__ . '/data/config-1.yml';
|
||||
$this->assertTrue(file_exists($path));
|
||||
|
||||
$loader->load($path);
|
||||
|
||||
$configFile = basename($loader->getSourceName());
|
||||
$this->assertEquals('config-1.yml', $configFile);
|
||||
|
||||
// Make sure that the data we loaded contained the expected keys
|
||||
$keys = $loader->keys();
|
||||
sort($keys);
|
||||
$keysString = implode(',', $keys);
|
||||
$this->assertEquals('c,m', $keysString);
|
||||
|
||||
$configData = $loader->export();
|
||||
$this->assertEquals('foo', $configData['c']);
|
||||
$this->assertEquals('1', $configData['m'][0]);
|
||||
}
|
||||
}
|
||||
168
core/lib/composer/vendor/consolidation/config/scenarios/symfony4/tests/ConfigOverlayTest.php
vendored
Normal file
168
core/lib/composer/vendor/consolidation/config/scenarios/symfony4/tests/ConfigOverlayTest.php
vendored
Normal file
@@ -0,0 +1,168 @@
|
||||
<?php
|
||||
namespace Consolidation\Config\Util;
|
||||
|
||||
use Consolidation\Config\Config;
|
||||
use Consolidation\Config\Loader\ConfigProcessor;
|
||||
use Consolidation\Config\Loader\YamlConfigLoader;
|
||||
|
||||
class ConfigOverlayTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
protected $overlay;
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$aliasContext = new Config();
|
||||
$aliasContext->import([
|
||||
'hidden-by-a' => 'alias hidden-by-a',
|
||||
'hidden-by-process' => 'alias hidden-by-process',
|
||||
'options' =>[
|
||||
'a-a' => 'alias-a',
|
||||
],
|
||||
'command' => [
|
||||
'foo' => [
|
||||
'bar' => [
|
||||
'command' => [
|
||||
'options' => [
|
||||
'a-b' => 'alias-b',
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
$configFileContext = new Config();
|
||||
$configFileContext->import([
|
||||
'hidden-by-cf' => 'config-file hidden-by-cf',
|
||||
'hidden-by-a' => 'config-file hidden-by-a',
|
||||
'hidden-by-process' => 'config-file hidden-by-process',
|
||||
'options' =>[
|
||||
'cf-a' => 'config-file-a',
|
||||
],
|
||||
'command' => [
|
||||
'foo' => [
|
||||
'bar' => [
|
||||
'command' => [
|
||||
'options' => [
|
||||
'cf-b' => 'config-file-b',
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
$this->overlay = new ConfigOverlay();
|
||||
$this->overlay->set('hidden-by-process', 'process-h');
|
||||
$this->overlay->addContext('cf', $configFileContext);
|
||||
$this->overlay->addContext('a', $aliasContext);
|
||||
$this->overlay->setDefault('df-a', 'default');
|
||||
$this->overlay->setDefault('hidden-by-a', 'default hidden-by-a');
|
||||
$this->overlay->setDefault('hidden-by-cf', 'default hidden-by-cf');
|
||||
$this->overlay->setDefault('hidden-by-process', 'default hidden-by-process');
|
||||
}
|
||||
|
||||
public function testGetPriority()
|
||||
{
|
||||
$this->assertEquals('process-h', $this->overlay->get('hidden-by-process'));
|
||||
$this->assertEquals('config-file hidden-by-cf', $this->overlay->get('hidden-by-cf'));
|
||||
$this->assertEquals('alias hidden-by-a', $this->overlay->get('hidden-by-a'));
|
||||
}
|
||||
|
||||
public function testDefault()
|
||||
{
|
||||
$this->assertEquals('alias-a', $this->overlay->get('options.a-a'));
|
||||
$this->assertEquals('alias-a', $this->overlay->get('options.a-a', 'ignored'));
|
||||
$this->assertEquals('default', $this->overlay->getDefault('df-a', 'ignored'));
|
||||
$this->assertEquals('nsv', $this->overlay->getDefault('a-a', 'nsv'));
|
||||
|
||||
$this->overlay->setDefault('df-a', 'new value');
|
||||
$this->assertEquals('new value', $this->overlay->getDefault('df-a', 'ignored'));
|
||||
}
|
||||
|
||||
public function testExport()
|
||||
{
|
||||
$data = $this->overlay->export();
|
||||
|
||||
$this->assertEquals('config-file-a', $data['options']['cf-a']);
|
||||
$this->assertEquals('alias-a', $data['options']['a-a']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Exception
|
||||
*/
|
||||
public function testImport()
|
||||
{
|
||||
$data = $this->overlay->import(['a' => 'value']);
|
||||
}
|
||||
|
||||
public function testMaintainPriority()
|
||||
{
|
||||
// Get and re-add the 'cf' context. Its priority should not change.
|
||||
$configFileContext = $this->overlay->getContext('cf');
|
||||
$this->overlay->addContext('cf', $configFileContext);
|
||||
|
||||
// These asserts are the same as in testGetPriority
|
||||
$this->assertEquals('process-h', $this->overlay->get('hidden-by-process'));
|
||||
$this->assertEquals('config-file hidden-by-cf', $this->overlay->get('hidden-by-cf'));
|
||||
$this->assertEquals('alias hidden-by-a', $this->overlay->get('hidden-by-a'));
|
||||
}
|
||||
|
||||
public function testChangePriority()
|
||||
{
|
||||
// Increase the priority of the 'cf' context. Now, it should have a higher
|
||||
// priority than the 'alias' context, but should still have a lower
|
||||
// priority than the 'process' context.
|
||||
$this->overlay->increasePriority('cf');
|
||||
|
||||
// These asserts are the same as in testGetPriority
|
||||
$this->assertEquals('process-h', $this->overlay->get('hidden-by-process'));
|
||||
$this->assertEquals('config-file hidden-by-cf', $this->overlay->get('hidden-by-cf'));
|
||||
|
||||
// This one has changed: the config-file value is now found instead
|
||||
// of the alias value.
|
||||
$this->assertEquals('config-file hidden-by-a', $this->overlay->get('hidden-by-a'));
|
||||
}
|
||||
|
||||
public function testPlaceholder()
|
||||
{
|
||||
$this->overlay->addPlaceholder('lower');
|
||||
|
||||
$higherContext = new Config();
|
||||
$higherContext->import(['priority-test' => 'higher']);
|
||||
|
||||
$lowerContext = new Config();
|
||||
$lowerContext->import(['priority-test' => 'lower']);
|
||||
|
||||
// Usually 'lower' would have the highest priority, since it is
|
||||
// added last. However, our earlier call to 'addPlaceholder' reserves
|
||||
// a spot for it, so the 'higher' context will end up with a higher
|
||||
// priority.
|
||||
$this->overlay->addContext('higher', $higherContext);
|
||||
$this->overlay->addContext('lower', $lowerContext);
|
||||
$this->assertEquals('higher', $this->overlay->get('priority-test', 'neither'));
|
||||
|
||||
// Test to see that we can change the value of the 'higher' context,
|
||||
// and the change will be reflected in the overlay.
|
||||
$higherContext->set('priority-test', 'changed');
|
||||
$this->assertEquals('changed', $this->overlay->get('priority-test', 'neither'));
|
||||
|
||||
// Test to see that the 'process' context still has the highest priority.
|
||||
$this->overlay->set('priority-test', 'process');
|
||||
$higherContext->set('priority-test', 'ignored');
|
||||
$this->assertEquals('process', $this->overlay->get('priority-test', 'neither'));
|
||||
}
|
||||
|
||||
public function testDoesNotHave()
|
||||
{
|
||||
$context = $this->overlay->getContext('no-such-context');
|
||||
$data = $context->export();
|
||||
$this->assertEquals('[]', json_encode($data));
|
||||
|
||||
$this->assertTrue(!$this->overlay->has('no-such-key'));
|
||||
$this->assertTrue(!$this->overlay->hasDefault('no-such-default'));
|
||||
|
||||
$this->assertEquals('no-such-value', $this->overlay->get('no-such-key', 'no-such-value'));
|
||||
|
||||
}
|
||||
}
|
||||
152
core/lib/composer/vendor/consolidation/config/scenarios/symfony4/tests/ConfigProcessorTest.php
vendored
Normal file
152
core/lib/composer/vendor/consolidation/config/scenarios/symfony4/tests/ConfigProcessorTest.php
vendored
Normal file
@@ -0,0 +1,152 @@
|
||||
<?php
|
||||
namespace Consolidation\Config\Loader;
|
||||
|
||||
use Consolidation\TestUtils\TestLoader;
|
||||
|
||||
class ConfigProcessorTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testConfigProcessorAdd()
|
||||
{
|
||||
$config1 = [
|
||||
'c' => 'foo',
|
||||
'm' => [1],
|
||||
];
|
||||
$config2 = [
|
||||
'b' => '${c}bar',
|
||||
'm' => [2],
|
||||
];
|
||||
$config3 = [
|
||||
'a' => '${b}baz',
|
||||
'm' => [3],
|
||||
];
|
||||
|
||||
$processor = new ConfigProcessor();
|
||||
$processor->add($config1);
|
||||
$processor->add($config2);
|
||||
$processor->add($config3);
|
||||
|
||||
$data = $processor->export();
|
||||
$this->assertEquals('foo', $data['c']);
|
||||
$this->assertEquals('foobar', $data['b']);
|
||||
$this->assertEquals('foobarbaz', $data['a']);
|
||||
}
|
||||
|
||||
public function processorForConfigMergeTest($provideSourceNames)
|
||||
{
|
||||
$config1 = [
|
||||
'm' => [
|
||||
'x' => 'x-1',
|
||||
'y' => [
|
||||
'r' => 'r-1',
|
||||
's' => 's-1',
|
||||
't' => 't-1',
|
||||
],
|
||||
'z' => 'z-1',
|
||||
],
|
||||
];
|
||||
$config2 = [
|
||||
'm' => [
|
||||
'w' => 'w-2',
|
||||
'y' => [
|
||||
'q' => 'q-2',
|
||||
's' => 's-2',
|
||||
],
|
||||
'z' => 'z-2',
|
||||
],
|
||||
];
|
||||
$config3 = [
|
||||
'm' => [
|
||||
'v' => 'v-3',
|
||||
'y' => [
|
||||
't' => 't-3',
|
||||
'u' => 'u-3',
|
||||
],
|
||||
'z' => 'z-3',
|
||||
],
|
||||
];
|
||||
|
||||
$processor = new ConfigProcessor();
|
||||
$testLoader = new TestLoader();
|
||||
|
||||
$testLoader->set($config1);
|
||||
$testLoader->setSourceName($provideSourceNames ? 'c-1' : '');
|
||||
$processor->extend($testLoader);
|
||||
|
||||
$testLoader->set($config2);
|
||||
$testLoader->setSourceName($provideSourceNames ? 'c-2' : '');
|
||||
$processor->extend($testLoader);
|
||||
|
||||
$testLoader->set($config3);
|
||||
$testLoader->setSourceName($provideSourceNames ? 'c-3' : '');
|
||||
$processor->extend($testLoader);
|
||||
|
||||
return $processor;
|
||||
}
|
||||
|
||||
public function testConfigProcessorMergeAssociative()
|
||||
{
|
||||
$processor = $this->processorForConfigMergeTest(false);
|
||||
$data = $processor->export();
|
||||
$this->assertEquals('{"m":{"x":"x-1","y":{"r":"r-1","s":"s-2","t":"t-3","q":"q-2","u":"u-3"},"z":"z-3","w":"w-2","v":"v-3"}}', json_encode($data));
|
||||
}
|
||||
|
||||
public function testConfigProcessorMergeAssociativeWithSourceNames()
|
||||
{
|
||||
$processor = $this->processorForConfigMergeTest(true);
|
||||
$sources = $processor->sources();
|
||||
$data = $processor->export();
|
||||
$this->assertEquals('{"m":{"x":"x-1","y":{"r":"r-1","s":"s-2","t":"t-3","q":"q-2","u":"u-3"},"z":"z-3","w":"w-2","v":"v-3"}}', json_encode($data));
|
||||
$this->assertEquals('c-1', $sources['m']['x']);
|
||||
$this->assertEquals('c-1', $sources['m']['y']['r']);
|
||||
$this->assertEquals('c-2', $sources['m']['w']);
|
||||
$this->assertEquals('c-2', $sources['m']['y']['s']);
|
||||
$this->assertEquals('c-3', $sources['m']['z']);
|
||||
$this->assertEquals('c-3', $sources['m']['y']['u']);
|
||||
}
|
||||
|
||||
public function testConfiProcessorSources()
|
||||
{
|
||||
$processor = new ConfigProcessor();
|
||||
$loader = new YamlConfigLoader();
|
||||
$processor->extend($loader->load(__DIR__ . '/data/config-1.yml'));
|
||||
$processor->extend($loader->load(__DIR__ . '/data/config-2.yml'));
|
||||
$processor->extend($loader->load(__DIR__ . '/data/config-3.yml'));
|
||||
|
||||
$sources = $processor->sources();
|
||||
|
||||
$data = $processor->export();
|
||||
$this->assertEquals('foo', $data['c']);
|
||||
$this->assertEquals('foobar', $data['b']);
|
||||
$this->assertEquals('foobarbaz', $data['a']);
|
||||
|
||||
$this->assertEquals('3', $data['m'][0]);
|
||||
|
||||
$this->assertEquals( __DIR__ . '/data/config-3.yml', $sources['a']);
|
||||
$this->assertEquals( __DIR__ . '/data/config-2.yml', $sources['b']);
|
||||
$this->assertEquals( __DIR__ . '/data/config-1.yml', $sources['c']);
|
||||
$this->assertEquals( __DIR__ . '/data/config-3.yml', $sources['m']);
|
||||
}
|
||||
|
||||
public function testConfiProcessorSourcesLoadInReverseOrder()
|
||||
{
|
||||
$processor = new ConfigProcessor();
|
||||
$loader = new YamlConfigLoader();
|
||||
$processor->extend($loader->load(__DIR__ . '/data/config-3.yml'));
|
||||
$processor->extend($loader->load(__DIR__ . '/data/config-2.yml'));
|
||||
$processor->extend($loader->load(__DIR__ . '/data/config-1.yml'));
|
||||
|
||||
$sources = $processor->sources();
|
||||
|
||||
$data = $processor->export();
|
||||
$this->assertEquals('foo', $data['c']);
|
||||
$this->assertEquals('foobar', $data['b']);
|
||||
$this->assertEquals('foobarbaz', $data['a']);
|
||||
|
||||
$this->assertEquals('1', $data['m'][0]);
|
||||
|
||||
$this->assertEquals( __DIR__ . '/data/config-3.yml', $sources['a']);
|
||||
$this->assertEquals( __DIR__ . '/data/config-2.yml', $sources['b']);
|
||||
$this->assertEquals( __DIR__ . '/data/config-1.yml', $sources['c']);
|
||||
$this->assertEquals( __DIR__ . '/data/config-1.yml', $sources['m']);
|
||||
}
|
||||
}
|
||||
140
core/lib/composer/vendor/consolidation/config/scenarios/symfony4/tests/ConfigTest.php
vendored
Normal file
140
core/lib/composer/vendor/consolidation/config/scenarios/symfony4/tests/ConfigTest.php
vendored
Normal file
@@ -0,0 +1,140 @@
|
||||
<?php
|
||||
namespace Consolidation\Config;
|
||||
|
||||
use Consolidation\Config\Loader\ConfigProcessor;
|
||||
use Consolidation\Config\Loader\YamlConfigLoader;
|
||||
|
||||
class ConfigTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testSetters()
|
||||
{
|
||||
// Pointless tests just to ensure everything is covered.
|
||||
$config = new Config();
|
||||
$config->set('foo', 'bar');
|
||||
$data = $config->export();
|
||||
$this->assertEquals('{"foo":"bar"}', json_encode($data));
|
||||
}
|
||||
|
||||
public function testCombine()
|
||||
{
|
||||
// Pointless tests just to ensure everything is covered.
|
||||
$config = new Config();
|
||||
$config->set('foo', 'bar');
|
||||
$config->set('baz', 'boz');
|
||||
$config2 = new Config();
|
||||
$config2->set('foo', 'fu');
|
||||
$config2->set('new', 'blue');
|
||||
$config->combine($config2->export());
|
||||
$this->assertEquals('fu', $config->get('foo'));
|
||||
$this->assertEquals('boz', $config->get('baz'));
|
||||
$this->assertEquals('blue', $config->get('new'));
|
||||
}
|
||||
|
||||
public function testDefault()
|
||||
{
|
||||
$data = [
|
||||
'a' => 'foo',
|
||||
'b' => 'bar',
|
||||
'c' => 'boz',
|
||||
];
|
||||
|
||||
$foo = ["foo" => "bar"];
|
||||
|
||||
$config = new Config($data);
|
||||
|
||||
$config->setDefault('c', 'other');
|
||||
$config->setDefault('d', 'other');
|
||||
$config->setDefault('f', $foo);
|
||||
|
||||
$this->assertEquals('foo', $config->get('a'));
|
||||
$this->assertEquals('boz', $config->get('c'));
|
||||
$this->assertEquals('other', $config->get('d'));
|
||||
$this->assertEquals('other', $config->getDefault('c'));
|
||||
$this->assertEquals('', $config->get('e'));
|
||||
$this->assertEquals('bar', $config->get('f.foo'));
|
||||
$this->assertEquals('{"foo":"bar"}', json_encode($config->get('f')));
|
||||
}
|
||||
|
||||
public function testDefaultsArray()
|
||||
{
|
||||
$data = ['a' => 'foo', 'b' => 'bar', 'c' => 'boz',];
|
||||
$defaults = ['d' => 'foo', 'e' => 'bar', 'f' => 'boz',];
|
||||
|
||||
// Create reflection class to test private methods
|
||||
$configClass = new \ReflectionClass("Consolidation\Config\Config");
|
||||
|
||||
// $defaults
|
||||
$defaultsProperty = $configClass->getProperty("defaults");
|
||||
$defaultsProperty->setAccessible(true);
|
||||
|
||||
// $getDefaults
|
||||
$getDefaultsMethod = $configClass->getMethod("getDefaults");
|
||||
$getDefaultsMethod->setAccessible(true);
|
||||
|
||||
// Test the config class
|
||||
$config = new Config($data);
|
||||
|
||||
// Set $config::defaults to an array to test getter and setter
|
||||
$defaultsProperty->setValue($config, $defaults);
|
||||
$this->assertTrue(is_array($defaultsProperty->getValue($config)));
|
||||
$this->assertInstanceOf('Dflydev\DotAccessData\Data',
|
||||
$getDefaultsMethod->invoke($config));
|
||||
|
||||
// Set $config::defaults to a string to test exception
|
||||
$defaultsProperty->setValue($config, "foo.bar");
|
||||
$this->setExpectedException("Exception");
|
||||
$getDefaultsMethod->invoke($config);
|
||||
}
|
||||
|
||||
public function testConfigurationWithCrossFileReferences()
|
||||
{
|
||||
$config = new Config();
|
||||
$processor = new ConfigProcessor();
|
||||
$loader = new YamlConfigLoader();
|
||||
$processor->extend($loader->load(__DIR__ . '/data/config-1.yml'));
|
||||
$processor->extend($loader->load(__DIR__ . '/data/config-2.yml'));
|
||||
$processor->extend($loader->load(__DIR__ . '/data/config-3.yml'));
|
||||
|
||||
// Does not fail if configuration file cannot be found
|
||||
$processor->extend($loader->load(__DIR__ . '/data/no-such-file.yml'));
|
||||
|
||||
// We must capture the sources before exporting, as export
|
||||
// dumps this information.
|
||||
$sources = $processor->sources();
|
||||
|
||||
$config->import($processor->export());
|
||||
|
||||
$this->assertEquals(implode(',', $config->get('m')), '3');
|
||||
$this->assertEquals($config->get('a'), 'foobarbaz');
|
||||
|
||||
$this->assertEquals($sources['a'], __DIR__ . '/data/config-3.yml');
|
||||
$this->assertEquals($sources['b'], __DIR__ . '/data/config-2.yml');
|
||||
$this->assertEquals($sources['c'], __DIR__ . '/data/config-1.yml');
|
||||
}
|
||||
|
||||
public function testConfigurationWithReverseOrderCrossFileReferences()
|
||||
{
|
||||
$config = new Config();
|
||||
$processor = new ConfigProcessor();
|
||||
$loader = new YamlConfigLoader();
|
||||
$processor->extend($loader->load(__DIR__ . '/data/config-3.yml'));
|
||||
$processor->extend($loader->load(__DIR__ . '/data/config-2.yml'));
|
||||
$processor->extend($loader->load(__DIR__ . '/data/config-1.yml'));
|
||||
|
||||
$sources = $processor->sources();
|
||||
$config->import($processor->export());
|
||||
|
||||
$this->assertEquals(implode(',', $config->get('m')), '1');
|
||||
|
||||
if (strpos($config->get('a'), '$') !== false) {
|
||||
throw new \PHPUnit_Framework_SkippedTestError(
|
||||
'Evaluation of cross-file references in reverse order not supported.'
|
||||
);
|
||||
}
|
||||
$this->assertEquals($config->get('a'), 'foobarbaz');
|
||||
|
||||
$this->assertEquals($sources['a'], __DIR__ . '/data/config-3.yml');
|
||||
$this->assertEquals($sources['b'], __DIR__ . '/data/config-2.yml');
|
||||
$this->assertEquals($sources['c'], __DIR__ . '/data/config-1.yml');
|
||||
}
|
||||
}
|
||||
3
core/lib/composer/vendor/consolidation/config/scenarios/symfony4/tests/data/config-1.yml
vendored
Normal file
3
core/lib/composer/vendor/consolidation/config/scenarios/symfony4/tests/data/config-1.yml
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
c: foo
|
||||
m:
|
||||
- 1
|
||||
3
core/lib/composer/vendor/consolidation/config/scenarios/symfony4/tests/data/config-2.yml
vendored
Normal file
3
core/lib/composer/vendor/consolidation/config/scenarios/symfony4/tests/data/config-2.yml
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
b: ${c}bar
|
||||
m:
|
||||
- 2
|
||||
3
core/lib/composer/vendor/consolidation/config/scenarios/symfony4/tests/data/config-3.yml
vendored
Normal file
3
core/lib/composer/vendor/consolidation/config/scenarios/symfony4/tests/data/config-3.yml
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
a: ${b}baz
|
||||
m:
|
||||
- 3
|
||||
23
core/lib/composer/vendor/consolidation/config/scenarios/symfony4/tests/scripts/install-scenario
vendored
Executable file
23
core/lib/composer/vendor/consolidation/config/scenarios/symfony4/tests/scripts/install-scenario
vendored
Executable file
@@ -0,0 +1,23 @@
|
||||
#!/bin/bash
|
||||
|
||||
SCENARIO=$1
|
||||
ACTION=${2-install}
|
||||
|
||||
dir=dependencies/${SCENARIO}
|
||||
if [ -z "$SCENARIO" ] ; then
|
||||
SCENARIO=default
|
||||
dir=.
|
||||
fi
|
||||
|
||||
|
||||
if [ ! -d "$dir" ] ; then
|
||||
echo "Requested scenario '${SCENARIO}' does not exist."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Switch to ${SCENARIO} scenario"
|
||||
|
||||
set -ex
|
||||
|
||||
composer -n --working-dir=$dir ${ACTION} --prefer-dist --no-scripts
|
||||
composer -n --working-dir=$dir info
|
||||
66
core/lib/composer/vendor/consolidation/config/scenarios/symfony4/tests/scripts/prep-dependencies
vendored
Executable file
66
core/lib/composer/vendor/consolidation/config/scenarios/symfony4/tests/scripts/prep-dependencies
vendored
Executable file
@@ -0,0 +1,66 @@
|
||||
#!/bin/bash
|
||||
|
||||
#
|
||||
# This script is called automatically on every `composer update`.
|
||||
# See "post-update-cmd" in the "scripts" section of composer.json.
|
||||
#
|
||||
# This script will create a derived composer.json / composer.lock
|
||||
# pair for every test scenario. Test scenarios are defined in the
|
||||
# "scenarios" file, which should be customized to suit the needs
|
||||
# of the project.
|
||||
#
|
||||
|
||||
SELF_DIRNAME="`dirname -- "$0"`"
|
||||
source ${SELF_DIRNAME}/scenarios
|
||||
|
||||
echo
|
||||
echo "::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::"
|
||||
echo "::"
|
||||
echo ":: Update dependencies for the following scenarios:"
|
||||
echo "::"
|
||||
echo ":: ${SCENARIOS}"
|
||||
echo "::"
|
||||
echo "::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::"
|
||||
echo
|
||||
|
||||
set -ex
|
||||
|
||||
for SCENARIO in ${SCENARIOS} ; do
|
||||
|
||||
dir=dependencies/${SCENARIO}
|
||||
|
||||
# Define indirect variable names
|
||||
stability_variable="stability_${SCENARIO}"
|
||||
requirement_variable="requirement_${SCENARIO}"
|
||||
platform_php_variable="platform_php_${SCENARIO}"
|
||||
|
||||
echo "### Create $dir/composer.json for ${SCENARIO} scenario"
|
||||
mkdir -p $dir
|
||||
cp composer.json $dir
|
||||
|
||||
# Then set our own platform php version if applicable (otherwise unset it)
|
||||
composer -n --working-dir=$dir config platform.php "${!platform_php_variable---unset}"
|
||||
|
||||
# Temporarily set our vendor directory to 'vendor'
|
||||
composer -n --working-dir=$dir config vendor-dir vendor
|
||||
|
||||
# Set an appropriate minimum stability for this version of Symfony
|
||||
composer -n --working-dir=$dir config minimum-stability "${!stability_variable-stable}"
|
||||
|
||||
# Add a constraint to limit the Symfony version
|
||||
composer -n --working-dir=$dir require --dev --no-update "${!requirement_variable}"
|
||||
|
||||
# Create the composer.lock file. Ignore the vendor directory created.
|
||||
composer -n --working-dir=$dir update --no-scripts
|
||||
|
||||
# Set the vendor directory to its final desired location.
|
||||
composer -n --working-dir=$dir config vendor-dir '../../vendor'
|
||||
|
||||
# The 'autoload' section specifies directory paths that are relative
|
||||
# to the composer.json file. We will drop in some symlinks so that
|
||||
# these paths will resolve as if the composer.json were in the root.
|
||||
for target in $AUTOLOAD_DIRECTORIES ; do
|
||||
ln -s -f ../../$target $dir
|
||||
done
|
||||
|
||||
done
|
||||
12
core/lib/composer/vendor/consolidation/config/scenarios/symfony4/tests/scripts/scenarios
vendored
Executable file
12
core/lib/composer/vendor/consolidation/config/scenarios/symfony4/tests/scripts/scenarios
vendored
Executable file
@@ -0,0 +1,12 @@
|
||||
#!/bin/bash
|
||||
|
||||
SCENARIOS="symfony2 symfony3 symfony4"
|
||||
|
||||
AUTOLOAD_DIRECTORIES='src tests'
|
||||
|
||||
platform_php_symfony2='5.4'
|
||||
platform_php_symfony3='5.6'
|
||||
|
||||
requirement_symfony2='symfony/console:^2.8'
|
||||
requirement_symfony3='symfony/console:^3'
|
||||
requirement_symfony4='symfony/console:^4'
|
||||
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace Consolidation\TestUtils;
|
||||
|
||||
class ApplyConfigTestTarget
|
||||
{
|
||||
protected $dir;
|
||||
protected $value;
|
||||
|
||||
/**
|
||||
* A proper setter for the 'dir' property
|
||||
*/
|
||||
public function dir($dir)
|
||||
{
|
||||
$this->dir = $dir;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* A getter for the 'dir' property that we will use to
|
||||
* determine if the setter was called.
|
||||
*/
|
||||
public function getDir()
|
||||
{
|
||||
return $this->dir;
|
||||
}
|
||||
|
||||
/**
|
||||
* A bad setter that does not return $this.
|
||||
*/
|
||||
public function bad($value)
|
||||
{
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* A getter for the bad setter.
|
||||
*/
|
||||
public function getBad()
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
}
|
||||
47
core/lib/composer/vendor/consolidation/config/scenarios/symfony4/tests/src/MyFooCommand.php
vendored
Normal file
47
core/lib/composer/vendor/consolidation/config/scenarios/symfony4/tests/src/MyFooCommand.php
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
namespace Consolidation\TestUtils;
|
||||
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
|
||||
class MyFooCommand extends Command
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
->setName('my:foo')
|
||||
->setDescription('My foo command.')
|
||||
->setHelp('This command tests command option injection by echoing its options')
|
||||
->addOption(
|
||||
'other',
|
||||
null,
|
||||
InputOption::VALUE_REQUIRED,
|
||||
'Some other option',
|
||||
'fish'
|
||||
)
|
||||
->addOption(
|
||||
'name',
|
||||
null,
|
||||
InputOption::VALUE_REQUIRED,
|
||||
'What is the name of the thing we are naming',
|
||||
'George'
|
||||
)
|
||||
->addOption(
|
||||
'dir',
|
||||
null,
|
||||
InputOption::VALUE_REQUIRED,
|
||||
'What is the base directory to use for this command',
|
||||
'/default/path'
|
||||
);
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$output->writeln('Enter my:foo');
|
||||
$output->writeln('dir: ' . $input->getOption('dir'));
|
||||
$output->writeln('name: ' . $input->getOption('name'));
|
||||
$output->writeln('other: ' . $input->getOption('other'));
|
||||
}
|
||||
}
|
||||
36
core/lib/composer/vendor/consolidation/config/scenarios/symfony4/tests/src/TestLoader.php
vendored
Normal file
36
core/lib/composer/vendor/consolidation/config/scenarios/symfony4/tests/src/TestLoader.php
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace Consolidation\TestUtils;
|
||||
|
||||
use Consolidation\Config\Loader\ConfigLoaderInterface;
|
||||
|
||||
class TestLoader implements ConfigLoaderInterface
|
||||
{
|
||||
protected $data;
|
||||
protected $sourceName;
|
||||
|
||||
public function set($data)
|
||||
{
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
public function setSourceName($name)
|
||||
{
|
||||
$this->sourceName = $name;
|
||||
}
|
||||
|
||||
public function export()
|
||||
{
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
public function keys()
|
||||
{
|
||||
return array_keys($this->data);
|
||||
}
|
||||
|
||||
public function getSourceName()
|
||||
{
|
||||
return $this->sourceName;
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
../../src
|
||||
73
core/lib/composer/vendor/consolidation/robo/scenarios/symfony2/src/Application.php
vendored
Normal file
73
core/lib/composer/vendor/consolidation/robo/scenarios/symfony2/src/Application.php
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
namespace Robo;
|
||||
|
||||
use Symfony\Component\Console\Application as SymfonyApplication;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
|
||||
class Application extends SymfonyApplication
|
||||
{
|
||||
/**
|
||||
* @param string $name
|
||||
* @param string $version
|
||||
*/
|
||||
public function __construct($name, $version)
|
||||
{
|
||||
parent::__construct($name, $version);
|
||||
|
||||
$this->getDefinition()
|
||||
->addOption(
|
||||
new InputOption('--simulate', null, InputOption::VALUE_NONE, 'Run in simulated mode (show what would have happened).')
|
||||
);
|
||||
$this->getDefinition()
|
||||
->addOption(
|
||||
new InputOption('--progress-delay', null, InputOption::VALUE_REQUIRED, 'Number of seconds before progress bar is displayed in long-running task collections. Default: 2s.', Config::DEFAULT_PROGRESS_DELAY)
|
||||
);
|
||||
|
||||
$this->getDefinition()
|
||||
->addOption(
|
||||
new InputOption('--define', '-D', InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Define a configuration item value.', [])
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $roboFile
|
||||
* @param string $roboClass
|
||||
*/
|
||||
public function addInitRoboFileCommand($roboFile, $roboClass)
|
||||
{
|
||||
$createRoboFile = new Command('init');
|
||||
$createRoboFile->setDescription("Intitalizes basic RoboFile in current dir");
|
||||
$createRoboFile->setCode(function () use ($roboClass, $roboFile) {
|
||||
$output = Robo::output();
|
||||
$output->writeln("<comment> ~~~ Welcome to Robo! ~~~~ </comment>");
|
||||
$output->writeln("<comment> ". basename($roboFile) ." will be created in the current directory </comment>");
|
||||
file_put_contents(
|
||||
$roboFile,
|
||||
'<?php'
|
||||
. "\n/**"
|
||||
. "\n * This is project's console commands configuration for Robo task runner."
|
||||
. "\n *"
|
||||
. "\n * @see http://robo.li/"
|
||||
. "\n */"
|
||||
. "\nclass " . $roboClass . " extends \\Robo\\Tasks\n{\n // define public methods as commands\n}"
|
||||
);
|
||||
$output->writeln("<comment> Edit this file to add your commands! </comment>");
|
||||
});
|
||||
$this->add($createRoboFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add self update command, do nothing if null is provided
|
||||
*
|
||||
* @param string $repository GitHub Repository for self update
|
||||
*/
|
||||
public function addSelfUpdateCommand($repository = null)
|
||||
{
|
||||
if (!$repository) {
|
||||
return;
|
||||
}
|
||||
$selfUpdateCommand = new SelfUpdateCommand($this->getName(), $this->getVersion(), $repository);
|
||||
$this->add($selfUpdateCommand);
|
||||
}
|
||||
}
|
||||
62
core/lib/composer/vendor/consolidation/robo/scenarios/symfony2/src/Collection/CallableTask.php
vendored
Normal file
62
core/lib/composer/vendor/consolidation/robo/scenarios/symfony2/src/Collection/CallableTask.php
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
namespace Robo\Collection;
|
||||
|
||||
use Robo\Result;
|
||||
use Robo\Contract\TaskInterface;
|
||||
use Robo\State\StateAwareInterface;
|
||||
use Robo\State\Data;
|
||||
|
||||
/**
|
||||
* Creates a task wrapper that converts any Callable into an
|
||||
* object that can be used directly with a task collection.
|
||||
*
|
||||
* It is not necessary to use this class directly; Collection will
|
||||
* automatically wrap Callables when they are added.
|
||||
*/
|
||||
class CallableTask implements TaskInterface
|
||||
{
|
||||
/**
|
||||
* @var callable
|
||||
*/
|
||||
protected $fn;
|
||||
|
||||
/**
|
||||
* @var \Robo\Contract\TaskInterface
|
||||
*/
|
||||
protected $reference;
|
||||
|
||||
public function __construct(callable $fn, TaskInterface $reference)
|
||||
{
|
||||
$this->fn = $fn;
|
||||
$this->reference = $reference;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Robo\Result
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
$result = call_user_func($this->fn, $this->getState());
|
||||
// If the function returns no result, then count it
|
||||
// as a success.
|
||||
if (!isset($result)) {
|
||||
$result = Result::success($this->reference);
|
||||
}
|
||||
// If the function returns a result, it must either return
|
||||
// a \Robo\Result or an exit code. In the later case, we
|
||||
// convert it to a \Robo\Result.
|
||||
if (!$result instanceof Result) {
|
||||
$result = new Result($this->reference, $result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getState()
|
||||
{
|
||||
if ($this->reference instanceof StateAwareInterface) {
|
||||
return $this->reference->getState();
|
||||
}
|
||||
return new Data();
|
||||
}
|
||||
}
|
||||
769
core/lib/composer/vendor/consolidation/robo/scenarios/symfony2/src/Collection/Collection.php
vendored
Normal file
769
core/lib/composer/vendor/consolidation/robo/scenarios/symfony2/src/Collection/Collection.php
vendored
Normal file
@@ -0,0 +1,769 @@
|
||||
<?php
|
||||
namespace Robo\Collection;
|
||||
|
||||
use Robo\Result;
|
||||
use Robo\State\Data;
|
||||
use Psr\Log\LogLevel;
|
||||
use Robo\Contract\TaskInterface;
|
||||
use Robo\Task\StackBasedTask;
|
||||
use Robo\Task\BaseTask;
|
||||
use Robo\TaskInfo;
|
||||
use Robo\Contract\WrappedTaskInterface;
|
||||
use Robo\Exception\TaskException;
|
||||
use Robo\Exception\TaskExitException;
|
||||
use Robo\Contract\CommandInterface;
|
||||
|
||||
use Robo\Contract\InflectionInterface;
|
||||
use Robo\State\StateAwareInterface;
|
||||
use Robo\State\StateAwareTrait;
|
||||
|
||||
/**
|
||||
* Group tasks into a collection that run together. Supports
|
||||
* rollback operations for handling error conditions.
|
||||
*
|
||||
* This is an internal class. Clients should use a CollectionBuilder
|
||||
* rather than direct use of the Collection class. @see CollectionBuilder.
|
||||
*
|
||||
* Below, the example FilesystemStack task is added to a collection,
|
||||
* and associated with a rollback task. If any of the operations in
|
||||
* the FilesystemStack, or if any of the other tasks also added to
|
||||
* the task collection should fail, then the rollback function is
|
||||
* called. Here, taskDeleteDir is used to remove partial results
|
||||
* of an unfinished task.
|
||||
*/
|
||||
class Collection extends BaseTask implements CollectionInterface, CommandInterface, StateAwareInterface
|
||||
{
|
||||
use StateAwareTrait;
|
||||
|
||||
/**
|
||||
* @var \Robo\Collection\Element[]
|
||||
*/
|
||||
protected $taskList = [];
|
||||
|
||||
/**
|
||||
* @var TaskInterface[]
|
||||
*/
|
||||
protected $rollbackStack = [];
|
||||
|
||||
/**
|
||||
* @var TaskInterface[]
|
||||
*/
|
||||
protected $completionStack = [];
|
||||
|
||||
/**
|
||||
* @var CollectionInterface
|
||||
*/
|
||||
protected $parentCollection;
|
||||
|
||||
/**
|
||||
* @var callable[]
|
||||
*/
|
||||
protected $deferredCallbacks = [];
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
protected $messageStoreKeys = [];
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->resetState();
|
||||
}
|
||||
|
||||
public function setProgressBarAutoDisplayInterval($interval)
|
||||
{
|
||||
if (!$this->progressIndicator) {
|
||||
return;
|
||||
}
|
||||
return $this->progressIndicator->setProgressBarAutoDisplayInterval($interval);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function add(TaskInterface $task, $name = self::UNNAMEDTASK)
|
||||
{
|
||||
$task = new CompletionWrapper($this, $task);
|
||||
$this->addToTaskList($name, $task);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function addCode(callable $code, $name = self::UNNAMEDTASK)
|
||||
{
|
||||
return $this->add(new CallableTask($code, $this), $name);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function addIterable($iterable, callable $code)
|
||||
{
|
||||
$callbackTask = (new IterationTask($iterable, $code, $this))->inflect($this);
|
||||
return $this->add($callbackTask);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function rollback(TaskInterface $rollbackTask)
|
||||
{
|
||||
// Rollback tasks always try as hard as they can, and never report failures.
|
||||
$rollbackTask = $this->ignoreErrorsTaskWrapper($rollbackTask);
|
||||
return $this->wrapAndRegisterRollback($rollbackTask);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function rollbackCode(callable $rollbackCode)
|
||||
{
|
||||
// Rollback tasks always try as hard as they can, and never report failures.
|
||||
$rollbackTask = $this->ignoreErrorsCodeWrapper($rollbackCode);
|
||||
return $this->wrapAndRegisterRollback($rollbackTask);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function completion(TaskInterface $completionTask)
|
||||
{
|
||||
$collection = $this;
|
||||
$completionRegistrationTask = new CallableTask(
|
||||
function () use ($collection, $completionTask) {
|
||||
|
||||
$collection->registerCompletion($completionTask);
|
||||
},
|
||||
$this
|
||||
);
|
||||
$this->addToTaskList(self::UNNAMEDTASK, $completionRegistrationTask);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function completionCode(callable $completionTask)
|
||||
{
|
||||
$completionTask = new CallableTask($completionTask, $this);
|
||||
return $this->completion($completionTask);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function before($name, $task, $nameOfTaskToAdd = self::UNNAMEDTASK)
|
||||
{
|
||||
return $this->addBeforeOrAfter(__FUNCTION__, $name, $task, $nameOfTaskToAdd);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function after($name, $task, $nameOfTaskToAdd = self::UNNAMEDTASK)
|
||||
{
|
||||
return $this->addBeforeOrAfter(__FUNCTION__, $name, $task, $nameOfTaskToAdd);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function progressMessage($text, $context = [], $level = LogLevel::NOTICE)
|
||||
{
|
||||
$context += ['name' => 'Progress'];
|
||||
$context += TaskInfo::getTaskContext($this);
|
||||
return $this->addCode(
|
||||
function () use ($level, $text, $context) {
|
||||
$context += $this->getState()->getData();
|
||||
$this->printTaskOutput($level, $text, $context);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Robo\Contract\TaskInterface $rollbackTask
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
protected function wrapAndRegisterRollback(TaskInterface $rollbackTask)
|
||||
{
|
||||
$collection = $this;
|
||||
$rollbackRegistrationTask = new CallableTask(
|
||||
function () use ($collection, $rollbackTask) {
|
||||
$collection->registerRollback($rollbackTask);
|
||||
},
|
||||
$this
|
||||
);
|
||||
$this->addToTaskList(self::UNNAMEDTASK, $rollbackRegistrationTask);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add either a 'before' or 'after' function or task.
|
||||
*
|
||||
* @param string $method
|
||||
* @param string $name
|
||||
* @param callable|TaskInterface $task
|
||||
* @param string $nameOfTaskToAdd
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
protected function addBeforeOrAfter($method, $name, $task, $nameOfTaskToAdd)
|
||||
{
|
||||
if (is_callable($task)) {
|
||||
$task = new CallableTask($task, $this);
|
||||
}
|
||||
$existingTask = $this->namedTask($name);
|
||||
$fn = [$existingTask, $method];
|
||||
call_user_func($fn, $task, $nameOfTaskToAdd);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap the provided task in a wrapper that will ignore
|
||||
* any errors or exceptions that may be produced. This
|
||||
* is useful, for example, in adding optional cleanup tasks
|
||||
* at the beginning of a task collection, to remove previous
|
||||
* results which may or may not exist.
|
||||
*
|
||||
* TODO: Provide some way to specify which sort of errors
|
||||
* are ignored, so that 'file not found' may be ignored,
|
||||
* but 'permission denied' reported?
|
||||
*
|
||||
* @param \Robo\Contract\TaskInterface $task
|
||||
*
|
||||
* @return \Robo\Collection\CallableTask
|
||||
*/
|
||||
public function ignoreErrorsTaskWrapper(TaskInterface $task)
|
||||
{
|
||||
// If the task is a stack-based task, then tell it
|
||||
// to try to run all of its operations, even if some
|
||||
// of them fail.
|
||||
if ($task instanceof StackBasedTask) {
|
||||
$task->stopOnFail(false);
|
||||
}
|
||||
$ignoreErrorsInTask = function () use ($task) {
|
||||
$data = [];
|
||||
try {
|
||||
$result = $this->runSubtask($task);
|
||||
$message = $result->getMessage();
|
||||
$data = $result->getData();
|
||||
$data['exitcode'] = $result->getExitCode();
|
||||
} catch (\Exception $e) {
|
||||
$message = $e->getMessage();
|
||||
}
|
||||
|
||||
return Result::success($task, $message, $data);
|
||||
};
|
||||
// Wrap our ignore errors callable in a task.
|
||||
return new CallableTask($ignoreErrorsInTask, $this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param callable $task
|
||||
*
|
||||
* @return \Robo\Collection\CallableTask
|
||||
*/
|
||||
public function ignoreErrorsCodeWrapper(callable $task)
|
||||
{
|
||||
return $this->ignoreErrorsTaskWrapper(new CallableTask($task, $this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of task names added to this collection.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function taskNames()
|
||||
{
|
||||
return array_keys($this->taskList);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to see if a specified task name exists.
|
||||
* n.b. before() and after() require that the named
|
||||
* task exist; use this function to test first, if
|
||||
* unsure.
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasTask($name)
|
||||
{
|
||||
return array_key_exists($name, $this->taskList);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find an existing named task.
|
||||
*
|
||||
* @param string $name
|
||||
* The name of the task to insert before. The named task MUST exist.
|
||||
*
|
||||
* @return Element
|
||||
* The task group for the named task. Generally this is only
|
||||
* used to call 'before()' and 'after()'.
|
||||
*/
|
||||
protected function namedTask($name)
|
||||
{
|
||||
if (!$this->hasTask($name)) {
|
||||
throw new \RuntimeException("Could not find task named $name");
|
||||
}
|
||||
return $this->taskList[$name];
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a list of tasks to our task collection.
|
||||
*
|
||||
* @param TaskInterface[] $tasks
|
||||
* An array of tasks to run with rollback protection
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function addTaskList(array $tasks)
|
||||
{
|
||||
foreach ($tasks as $name => $task) {
|
||||
$this->add($task, $name);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the provided task to our task list.
|
||||
*
|
||||
* @param string $name
|
||||
* @param \Robo\Contract\TaskInterface $task
|
||||
*
|
||||
* @return \Robo\Collection\Collection
|
||||
*/
|
||||
protected function addToTaskList($name, TaskInterface $task)
|
||||
{
|
||||
// All tasks are stored in a task group so that we have a place
|
||||
// to hang 'before' and 'after' tasks.
|
||||
$taskGroup = new Element($task);
|
||||
return $this->addCollectionElementToTaskList($name, $taskGroup);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int|string $name
|
||||
* @param \Robo\Collection\Element $taskGroup
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
protected function addCollectionElementToTaskList($name, Element $taskGroup)
|
||||
{
|
||||
// If a task name is not provided, then we'll let php pick
|
||||
// the array index.
|
||||
if (Result::isUnnamed($name)) {
|
||||
$this->taskList[] = $taskGroup;
|
||||
return $this;
|
||||
}
|
||||
// If we are replacing an existing task with the
|
||||
// same name, ensure that our new task is added to
|
||||
// the end.
|
||||
$this->taskList[$name] = $taskGroup;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the parent collection. This is necessary so that nested
|
||||
* collections' rollback and completion tasks can be added to the
|
||||
* top-level collection, ensuring that the rollbacks for a collection
|
||||
* will run if any later task fails.
|
||||
*
|
||||
* @param \Robo\Collection\NestedCollectionInterface $parentCollection
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setParentCollection(NestedCollectionInterface $parentCollection)
|
||||
{
|
||||
$this->parentCollection = $parentCollection;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the appropriate parent collection to use
|
||||
*
|
||||
* @return CollectionInterface
|
||||
*/
|
||||
public function getParentCollection()
|
||||
{
|
||||
return $this->parentCollection ? $this->parentCollection : $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a rollback task to run if there is any failure.
|
||||
*
|
||||
* Clients are free to add tasks to the rollback stack as
|
||||
* desired; however, usually it is preferable to call
|
||||
* Collection::rollback() instead. With that function,
|
||||
* the rollback function will only be called if all of the
|
||||
* tasks added before it complete successfully, AND some later
|
||||
* task fails.
|
||||
*
|
||||
* One example of a good use-case for registering a callback
|
||||
* function directly is to add a task that sends notification
|
||||
* when a task fails.
|
||||
*
|
||||
* @param TaskInterface $rollbackTask
|
||||
* The rollback task to run on failure.
|
||||
*/
|
||||
public function registerRollback(TaskInterface $rollbackTask)
|
||||
{
|
||||
if ($this->parentCollection) {
|
||||
return $this->parentCollection->registerRollback($rollbackTask);
|
||||
}
|
||||
if ($rollbackTask) {
|
||||
$this->rollbackStack[] = $rollbackTask;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a completion task to run once all other tasks finish.
|
||||
* Completion tasks run whether or not a rollback operation was
|
||||
* triggered. They do not trigger rollbacks if they fail.
|
||||
*
|
||||
* The typical use-case for a completion function is to clean up
|
||||
* temporary objects (e.g. temporary folders). The preferred
|
||||
* way to do that, though, is to use Temporary::wrap().
|
||||
*
|
||||
* On failures, completion tasks will run after all rollback tasks.
|
||||
* If one task collection is nested inside another task collection,
|
||||
* then the nested collection's completion tasks will run as soon as
|
||||
* the nested task completes; they are not deferred to the end of
|
||||
* the containing collection's execution.
|
||||
*
|
||||
* @param TaskInterface $completionTask
|
||||
* The completion task to run at the end of all other operations.
|
||||
*/
|
||||
public function registerCompletion(TaskInterface $completionTask)
|
||||
{
|
||||
if ($this->parentCollection) {
|
||||
return $this->parentCollection->registerCompletion($completionTask);
|
||||
}
|
||||
if ($completionTask) {
|
||||
// Completion tasks always try as hard as they can, and never report failures.
|
||||
$completionTask = $this->ignoreErrorsTaskWrapper($completionTask);
|
||||
$this->completionStack[] = $completionTask;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the count of steps in this collection
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function progressIndicatorSteps()
|
||||
{
|
||||
$steps = 0;
|
||||
foreach ($this->taskList as $name => $taskGroup) {
|
||||
$steps += $taskGroup->progressIndicatorSteps();
|
||||
}
|
||||
return $steps;
|
||||
}
|
||||
|
||||
/**
|
||||
* A Collection of tasks can provide a command via `getCommand()`
|
||||
* if it contains a single task, and that task implements CommandInterface.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws \Robo\Exception\TaskException
|
||||
*/
|
||||
public function getCommand()
|
||||
{
|
||||
if (empty($this->taskList)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (count($this->taskList) > 1) {
|
||||
// TODO: We could potentially iterate over the items in the collection
|
||||
// and concatenate the result of getCommand() from each one, and fail
|
||||
// only if we encounter a command that is not a CommandInterface.
|
||||
throw new TaskException($this, "getCommand() does not work on arbitrary collections of tasks.");
|
||||
}
|
||||
|
||||
$taskElement = reset($this->taskList);
|
||||
$task = $taskElement->getTask();
|
||||
$task = ($task instanceof WrappedTaskInterface) ? $task->original() : $task;
|
||||
if ($task instanceof CommandInterface) {
|
||||
return $task->getCommand();
|
||||
}
|
||||
|
||||
throw new TaskException($task, get_class($task) . " does not implement CommandInterface, so can't be used to provide a command");
|
||||
}
|
||||
|
||||
/**
|
||||
* Run our tasks, and roll back if necessary.
|
||||
*
|
||||
* @return \Robo\Result
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
$result = $this->runWithoutCompletion();
|
||||
$this->complete();
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Robo\Result
|
||||
*/
|
||||
private function runWithoutCompletion()
|
||||
{
|
||||
$result = Result::success($this);
|
||||
|
||||
if (empty($this->taskList)) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
$this->startProgressIndicator();
|
||||
if ($result->wasSuccessful()) {
|
||||
foreach ($this->taskList as $name => $taskGroup) {
|
||||
$taskList = $taskGroup->getTaskList();
|
||||
$result = $this->runTaskList($name, $taskList, $result);
|
||||
if (!$result->wasSuccessful()) {
|
||||
$this->fail();
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
$this->taskList = [];
|
||||
}
|
||||
$this->stopProgressIndicator();
|
||||
$result['time'] = $this->getExecutionTime();
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run every task in a list, but only up to the first failure.
|
||||
* Return the failing result, or success if all tasks run.
|
||||
*
|
||||
* @param string $name
|
||||
* @param TaskInterface[] $taskList
|
||||
* @param \Robo\Result $result
|
||||
*
|
||||
* @return \Robo\Result
|
||||
*
|
||||
* @throws \Robo\Exception\TaskExitException
|
||||
*/
|
||||
private function runTaskList($name, array $taskList, Result $result)
|
||||
{
|
||||
try {
|
||||
foreach ($taskList as $taskName => $task) {
|
||||
$taskResult = $this->runSubtask($task);
|
||||
$this->advanceProgressIndicator();
|
||||
// If the current task returns an error code, then stop
|
||||
// execution and signal a rollback.
|
||||
if (!$taskResult->wasSuccessful()) {
|
||||
return $taskResult;
|
||||
}
|
||||
// We accumulate our results into a field so that tasks that
|
||||
// have a reference to the collection may examine and modify
|
||||
// the incremental results, if they wish.
|
||||
$key = Result::isUnnamed($taskName) ? $name : $taskName;
|
||||
$result->accumulate($key, $taskResult);
|
||||
// The result message will be the message of the last task executed.
|
||||
$result->setMessage($taskResult->getMessage());
|
||||
}
|
||||
} catch (TaskExitException $exitException) {
|
||||
$this->fail();
|
||||
throw $exitException;
|
||||
} catch (\Exception $e) {
|
||||
// Tasks typically should not throw, but if one does, we will
|
||||
// convert it into an error and roll back.
|
||||
return Result::fromException($task, $e, $result->getData());
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Force the rollback functions to run
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function fail()
|
||||
{
|
||||
$this->disableProgressIndicator();
|
||||
$this->runRollbackTasks();
|
||||
$this->complete();
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Force the completion functions to run
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function complete()
|
||||
{
|
||||
$this->detatchProgressIndicator();
|
||||
$this->runTaskListIgnoringFailures($this->completionStack);
|
||||
$this->reset();
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset this collection, removing all tasks.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function reset()
|
||||
{
|
||||
$this->taskList = [];
|
||||
$this->completionStack = [];
|
||||
$this->rollbackStack = [];
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run all of our rollback tasks.
|
||||
*
|
||||
* Note that Collection does not implement RollbackInterface, but
|
||||
* it may still be used as a task inside another task collection
|
||||
* (i.e. you can nest task collections, if desired).
|
||||
*/
|
||||
protected function runRollbackTasks()
|
||||
{
|
||||
$this->runTaskListIgnoringFailures($this->rollbackStack);
|
||||
// Erase our rollback stack once we have finished rolling
|
||||
// everything back. This will allow us to potentially use
|
||||
// a command collection more than once (e.g. to retry a
|
||||
// failed operation after doing some error recovery).
|
||||
$this->rollbackStack = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TaskInterface|NestedCollectionInterface|WrappedTaskInterface $task
|
||||
*
|
||||
* @return \Robo\Result
|
||||
*/
|
||||
protected function runSubtask($task)
|
||||
{
|
||||
$original = ($task instanceof WrappedTaskInterface) ? $task->original() : $task;
|
||||
$this->setParentCollectionForTask($original, $this->getParentCollection());
|
||||
if ($original instanceof InflectionInterface) {
|
||||
$original->inflect($this);
|
||||
}
|
||||
if ($original instanceof StateAwareInterface) {
|
||||
$original->setState($this->getState());
|
||||
}
|
||||
$this->doDeferredInitialization($original);
|
||||
$taskResult = $task->run();
|
||||
$taskResult = Result::ensureResult($task, $taskResult);
|
||||
$this->doStateUpdates($original, $taskResult);
|
||||
return $taskResult;
|
||||
}
|
||||
|
||||
protected function doStateUpdates($task, Data $taskResult)
|
||||
{
|
||||
$this->updateState($taskResult);
|
||||
$key = spl_object_hash($task);
|
||||
if (array_key_exists($key, $this->messageStoreKeys)) {
|
||||
$state = $this->getState();
|
||||
list($stateKey, $sourceKey) = $this->messageStoreKeys[$key];
|
||||
$value = empty($sourceKey) ? $taskResult->getMessage() : $taskResult[$sourceKey];
|
||||
$state[$stateKey] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
public function storeState($task, $key, $source = '')
|
||||
{
|
||||
$this->messageStoreKeys[spl_object_hash($task)] = [$key, $source];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function deferTaskConfiguration($task, $functionName, $stateKey)
|
||||
{
|
||||
return $this->defer(
|
||||
$task,
|
||||
function ($task, $state) use ($functionName, $stateKey) {
|
||||
$fn = [$task, $functionName];
|
||||
$value = $state[$stateKey];
|
||||
$fn($value);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Defer execution of a callback function until just before a task
|
||||
* runs. Use this time to provide more settings for the task, e.g. from
|
||||
* the collection's shared state, which is populated with the results
|
||||
* of previous test runs.
|
||||
*/
|
||||
public function defer($task, $callback)
|
||||
{
|
||||
$this->deferredCallbacks[spl_object_hash($task)][] = $callback;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function doDeferredInitialization($task)
|
||||
{
|
||||
// If the task is a state consumer, then call its receiveState method
|
||||
if ($task instanceof \Robo\State\Consumer) {
|
||||
$task->receiveState($this->getState());
|
||||
}
|
||||
|
||||
// Check and see if there are any deferred callbacks for this task.
|
||||
$key = spl_object_hash($task);
|
||||
if (!array_key_exists($key, $this->deferredCallbacks)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Call all of the deferred callbacks
|
||||
foreach ($this->deferredCallbacks[$key] as $fn) {
|
||||
$fn($task, $this->getState());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TaskInterface|NestedCollectionInterface|WrappedTaskInterface $task
|
||||
* @param $parentCollection
|
||||
*/
|
||||
protected function setParentCollectionForTask($task, $parentCollection)
|
||||
{
|
||||
if ($task instanceof NestedCollectionInterface) {
|
||||
$task->setParentCollection($parentCollection);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Run all of the tasks in a provided list, ignoring failures.
|
||||
* This is used to roll back or complete.
|
||||
*
|
||||
* @param TaskInterface[] $taskList
|
||||
*/
|
||||
protected function runTaskListIgnoringFailures(array $taskList)
|
||||
{
|
||||
foreach ($taskList as $task) {
|
||||
try {
|
||||
$this->runSubtask($task);
|
||||
} catch (\Exception $e) {
|
||||
// Ignore rollback failures.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Give all of our tasks to the provided collection builder.
|
||||
*
|
||||
* @param CollectionBuilder $builder
|
||||
*/
|
||||
public function transferTasks($builder)
|
||||
{
|
||||
foreach ($this->taskList as $name => $taskGroup) {
|
||||
// TODO: We are abandoning all of our before and after tasks here.
|
||||
// At the moment, transferTasks is only called under conditions where
|
||||
// there will be none of these, but care should be taken if that changes.
|
||||
$task = $taskGroup->getTask();
|
||||
$builder->addTaskToCollection($task);
|
||||
}
|
||||
$this->reset();
|
||||
}
|
||||
}
|
||||
571
core/lib/composer/vendor/consolidation/robo/scenarios/symfony2/src/Collection/CollectionBuilder.php
vendored
Normal file
571
core/lib/composer/vendor/consolidation/robo/scenarios/symfony2/src/Collection/CollectionBuilder.php
vendored
Normal file
@@ -0,0 +1,571 @@
|
||||
<?php
|
||||
namespace Robo\Collection;
|
||||
|
||||
use Consolidation\Config\Inject\ConfigForSetters;
|
||||
use Robo\Config\Config;
|
||||
use Psr\Log\LogLevel;
|
||||
use Robo\Contract\InflectionInterface;
|
||||
use Robo\Contract\TaskInterface;
|
||||
use Robo\Contract\CompletionInterface;
|
||||
use Robo\Contract\WrappedTaskInterface;
|
||||
use Robo\Task\Simulator;
|
||||
use ReflectionClass;
|
||||
use Robo\Task\BaseTask;
|
||||
use Robo\Contract\BuilderAwareInterface;
|
||||
use Robo\Contract\CommandInterface;
|
||||
use Robo\Contract\VerbosityThresholdInterface;
|
||||
use Robo\State\StateAwareInterface;
|
||||
use Robo\State\StateAwareTrait;
|
||||
use Robo\Result;
|
||||
|
||||
/**
|
||||
* Creates a collection, and adds tasks to it. The collection builder
|
||||
* offers a streamlined chained-initialization mechanism for easily
|
||||
* creating task groups. Facilities for creating working and temporary
|
||||
* directories are also provided.
|
||||
*
|
||||
* ``` php
|
||||
* <?php
|
||||
* $result = $this->collectionBuilder()
|
||||
* ->taskFilesystemStack()
|
||||
* ->mkdir('g')
|
||||
* ->touch('g/g.txt')
|
||||
* ->rollback(
|
||||
* $this->taskDeleteDir('g')
|
||||
* )
|
||||
* ->taskFilesystemStack()
|
||||
* ->mkdir('g/h')
|
||||
* ->touch('g/h/h.txt')
|
||||
* ->taskFilesystemStack()
|
||||
* ->mkdir('g/h/i/c')
|
||||
* ->touch('g/h/i/i.txt')
|
||||
* ->run()
|
||||
* ?>
|
||||
*
|
||||
* In the example above, the `taskDeleteDir` will be called if
|
||||
* ```
|
||||
*/
|
||||
class CollectionBuilder extends BaseTask implements NestedCollectionInterface, WrappedTaskInterface, CommandInterface, StateAwareInterface
|
||||
{
|
||||
use StateAwareTrait;
|
||||
|
||||
/**
|
||||
* @var \Robo\Tasks
|
||||
*/
|
||||
protected $commandFile;
|
||||
|
||||
/**
|
||||
* @var CollectionInterface
|
||||
*/
|
||||
protected $collection;
|
||||
|
||||
/**
|
||||
* @var TaskInterface
|
||||
*/
|
||||
protected $currentTask;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $simulated;
|
||||
|
||||
/**
|
||||
* @param \Robo\Tasks $commandFile
|
||||
*/
|
||||
public function __construct($commandFile)
|
||||
{
|
||||
$this->commandFile = $commandFile;
|
||||
$this->resetState();
|
||||
}
|
||||
|
||||
public static function create($container, $commandFile)
|
||||
{
|
||||
$builder = new self($commandFile);
|
||||
|
||||
$builder->setLogger($container->get('logger'));
|
||||
$builder->setProgressIndicator($container->get('progressIndicator'));
|
||||
$builder->setConfig($container->get('config'));
|
||||
$builder->setOutputAdapter($container->get('outputAdapter'));
|
||||
|
||||
return $builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $simulated
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function simulated($simulated = true)
|
||||
{
|
||||
$this->simulated = $simulated;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isSimulated()
|
||||
{
|
||||
if (!isset($this->simulated)) {
|
||||
$this->simulated = $this->getConfig()->get(Config::SIMULATE);
|
||||
}
|
||||
return $this->simulated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a temporary directory to work in. When the collection
|
||||
* completes or rolls back, the temporary directory will be deleted.
|
||||
* Returns the path to the location where the directory will be
|
||||
* created.
|
||||
*
|
||||
* @param string $prefix
|
||||
* @param string $base
|
||||
* @param bool $includeRandomPart
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function tmpDir($prefix = 'tmp', $base = '', $includeRandomPart = true)
|
||||
{
|
||||
// n.b. Any task that the builder is asked to create is
|
||||
// automatically added to the builder's collection, and
|
||||
// wrapped in the builder object. Therefore, the result
|
||||
// of any call to `taskFoo()` from within the builder will
|
||||
// always be `$this`.
|
||||
return $this->taskTmpDir($prefix, $base, $includeRandomPart)->getPath();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a working directory to hold results. A temporary directory
|
||||
* is first created to hold the intermediate results. After the
|
||||
* builder finishes, the work directory is moved into its final location;
|
||||
* any results already in place will be moved out of the way and
|
||||
* then deleted.
|
||||
*
|
||||
* @param string $finalDestination The path where the working directory
|
||||
* will be moved once the task collection completes.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function workDir($finalDestination)
|
||||
{
|
||||
// Creating the work dir task in this context adds it to our task collection.
|
||||
return $this->taskWorkDir($finalDestination)->getPath();
|
||||
}
|
||||
|
||||
public function addTask(TaskInterface $task)
|
||||
{
|
||||
$this->getCollection()->add($task);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add arbitrary code to execute as a task.
|
||||
*
|
||||
* @see \Robo\Collection\CollectionInterface::addCode
|
||||
*
|
||||
* @param callable $code
|
||||
* @param int|string $name
|
||||
* @return $this
|
||||
*/
|
||||
public function addCode(callable $code, $name = \Robo\Collection\CollectionInterface::UNNAMEDTASK)
|
||||
{
|
||||
$this->getCollection()->addCode($code, $name);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a list of tasks to our task collection.
|
||||
*
|
||||
* @param TaskInterface[] $tasks
|
||||
* An array of tasks to run with rollback protection
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function addTaskList(array $tasks)
|
||||
{
|
||||
$this->getCollection()->addTaskList($tasks);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function rollback(TaskInterface $task)
|
||||
{
|
||||
// Ensure that we have a collection if we are going to add
|
||||
// a rollback function.
|
||||
$this->getCollection()->rollback($task);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function rollbackCode(callable $rollbackCode)
|
||||
{
|
||||
$this->getCollection()->rollbackCode($rollbackCode);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function completion(TaskInterface $task)
|
||||
{
|
||||
$this->getCollection()->completion($task);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function completionCode(callable $completionCode)
|
||||
{
|
||||
$this->getCollection()->completionCode($completionCode);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $text
|
||||
* @param array $context
|
||||
* @param string $level
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function progressMessage($text, $context = [], $level = LogLevel::NOTICE)
|
||||
{
|
||||
$this->getCollection()->progressMessage($text, $context, $level);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Robo\Collection\NestedCollectionInterface $parentCollection
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setParentCollection(NestedCollectionInterface $parentCollection)
|
||||
{
|
||||
$this->getCollection()->setParentCollection($parentCollection);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the factory method of each task; adds the current
|
||||
* task to the task builder.
|
||||
*
|
||||
* TODO: protected
|
||||
*
|
||||
* @param TaskInterface $task
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function addTaskToCollection($task)
|
||||
{
|
||||
// Postpone creation of the collection until the second time
|
||||
// we are called. At that time, $this->currentTask will already
|
||||
// be populated. We call 'getCollection()' so that it will
|
||||
// create the collection and add the current task to it.
|
||||
// Note, however, that if our only tasks implements NestedCollectionInterface,
|
||||
// then we should force this builder to use a collection.
|
||||
if (!$this->collection && (isset($this->currentTask) || ($task instanceof NestedCollectionInterface))) {
|
||||
$this->getCollection();
|
||||
}
|
||||
$this->currentTask = $task;
|
||||
if ($this->collection) {
|
||||
$this->collection->add($task);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getState()
|
||||
{
|
||||
$collection = $this->getCollection();
|
||||
return $collection->getState();
|
||||
}
|
||||
|
||||
public function storeState($key, $source = '')
|
||||
{
|
||||
return $this->callCollectionStateFuntion(__FUNCTION__, func_get_args());
|
||||
}
|
||||
|
||||
public function deferTaskConfiguration($functionName, $stateKey)
|
||||
{
|
||||
return $this->callCollectionStateFuntion(__FUNCTION__, func_get_args());
|
||||
}
|
||||
|
||||
public function defer($callback)
|
||||
{
|
||||
return $this->callCollectionStateFuntion(__FUNCTION__, func_get_args());
|
||||
}
|
||||
|
||||
protected function callCollectionStateFuntion($functionName, $args)
|
||||
{
|
||||
$currentTask = ($this->currentTask instanceof WrappedTaskInterface) ? $this->currentTask->original() : $this->currentTask;
|
||||
|
||||
array_unshift($args, $currentTask);
|
||||
$collection = $this->getCollection();
|
||||
$fn = [$collection, $functionName];
|
||||
|
||||
call_user_func_array($fn, $args);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setVerbosityThreshold($verbosityThreshold)
|
||||
{
|
||||
$currentTask = ($this->currentTask instanceof WrappedTaskInterface) ? $this->currentTask->original() : $this->currentTask;
|
||||
if ($currentTask) {
|
||||
$currentTask->setVerbosityThreshold($verbosityThreshold);
|
||||
return $this;
|
||||
}
|
||||
parent::setVerbosityThreshold($verbosityThreshold);
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the current task for this collection builder.
|
||||
* TODO: Not needed?
|
||||
*
|
||||
* @return \Robo\Contract\TaskInterface
|
||||
*/
|
||||
public function getCollectionBuilderCurrentTask()
|
||||
{
|
||||
return $this->currentTask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new builder with its own task collection
|
||||
*
|
||||
* @return CollectionBuilder
|
||||
*/
|
||||
public function newBuilder()
|
||||
{
|
||||
$collectionBuilder = new self($this->commandFile);
|
||||
$collectionBuilder->inflect($this);
|
||||
$collectionBuilder->simulated($this->isSimulated());
|
||||
$collectionBuilder->setVerbosityThreshold($this->verbosityThreshold());
|
||||
$collectionBuilder->setState($this->getState());
|
||||
|
||||
return $collectionBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calling the task builder with methods of the current
|
||||
* task calls through to that method of the task.
|
||||
*
|
||||
* There is extra complexity in this function that could be
|
||||
* simplified if we attached the 'LoadAllTasks' and custom tasks
|
||||
* to the collection builder instead of the RoboFile. While that
|
||||
* change would be a better design overall, it would require that
|
||||
* the user do a lot more work to set up and use custom tasks.
|
||||
* We therefore take on some additional complexity here in order
|
||||
* to allow users to maintain their tasks in their RoboFile, which
|
||||
* is much more convenient.
|
||||
*
|
||||
* Calls to $this->collectionBuilder()->taskFoo() cannot be made
|
||||
* directly because all of the task methods are protected. These
|
||||
* calls will therefore end up here. If the method name begins
|
||||
* with 'task', then it is eligible to be used with the builder.
|
||||
*
|
||||
* When we call getBuiltTask, below, it will use the builder attached
|
||||
* to the commandfile to build the task. However, this is not what we
|
||||
* want: the task needs to be built from THIS collection builder, so that
|
||||
* it will be affected by whatever state is active in this builder.
|
||||
* To do this, we have two choices: 1) save and restore the builder
|
||||
* in the commandfile, or 2) clone the commandfile and set this builder
|
||||
* on the copy. 1) is vulnerable to failure in multithreaded environments
|
||||
* (currently not supported), while 2) might cause confusion if there
|
||||
* is shared state maintained in the commandfile, which is in the
|
||||
* domain of the user.
|
||||
*
|
||||
* Note that even though we are setting up the commandFile to
|
||||
* use this builder, getBuiltTask always creates a new builder
|
||||
* (which is constructed using all of the settings from the
|
||||
* commandFile's builder), and the new task is added to that.
|
||||
* We therefore need to transfer the newly built task into this
|
||||
* builder. The temporary builder is discarded.
|
||||
*
|
||||
* @param string $fn
|
||||
* @param array $args
|
||||
*
|
||||
* @return $this|mixed
|
||||
*/
|
||||
public function __call($fn, $args)
|
||||
{
|
||||
if (preg_match('#^task[A-Z]#', $fn) && (method_exists($this->commandFile, 'getBuiltTask'))) {
|
||||
$saveBuilder = $this->commandFile->getBuilder();
|
||||
$this->commandFile->setBuilder($this);
|
||||
$temporaryBuilder = $this->commandFile->getBuiltTask($fn, $args);
|
||||
$this->commandFile->setBuilder($saveBuilder);
|
||||
if (!$temporaryBuilder) {
|
||||
throw new \BadMethodCallException("No such method $fn: task does not exist in " . get_class($this->commandFile));
|
||||
}
|
||||
$temporaryBuilder->getCollection()->transferTasks($this);
|
||||
return $this;
|
||||
}
|
||||
if (!isset($this->currentTask)) {
|
||||
throw new \BadMethodCallException("No such method $fn: current task undefined in collection builder.");
|
||||
}
|
||||
// If the method called is a method of the current task,
|
||||
// then call through to the current task's setter method.
|
||||
$result = call_user_func_array([$this->currentTask, $fn], $args);
|
||||
|
||||
// If something other than a setter method is called, then return its result.
|
||||
$currentTask = ($this->currentTask instanceof WrappedTaskInterface) ? $this->currentTask->original() : $this->currentTask;
|
||||
if (isset($result) && ($result !== $currentTask)) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct the desired task and add it to this builder.
|
||||
*
|
||||
* @param string|object $name
|
||||
* @param array $args
|
||||
*
|
||||
* @return \Robo\Collection\CollectionBuilder
|
||||
*/
|
||||
public function build($name, $args)
|
||||
{
|
||||
$reflection = new ReflectionClass($name);
|
||||
$task = $reflection->newInstanceArgs($args);
|
||||
if (!$task) {
|
||||
throw new RuntimeException("Can not construct task $name");
|
||||
}
|
||||
$task = $this->fixTask($task, $args);
|
||||
$this->configureTask($name, $task);
|
||||
return $this->addTaskToCollection($task);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param InflectionInterface $task
|
||||
* @param array $args
|
||||
*
|
||||
* @return \Robo\Collection\CompletionWrapper|\Robo\Task\Simulator
|
||||
*/
|
||||
protected function fixTask($task, $args)
|
||||
{
|
||||
if ($task instanceof InflectionInterface) {
|
||||
$task->inflect($this);
|
||||
}
|
||||
if ($task instanceof BuilderAwareInterface) {
|
||||
$task->setBuilder($this);
|
||||
}
|
||||
if ($task instanceof VerbosityThresholdInterface) {
|
||||
$task->setVerbosityThreshold($this->verbosityThreshold());
|
||||
}
|
||||
|
||||
// Do not wrap our wrappers.
|
||||
if ($task instanceof CompletionWrapper || $task instanceof Simulator) {
|
||||
return $task;
|
||||
}
|
||||
|
||||
// Remember whether or not this is a task before
|
||||
// it gets wrapped in any decorator.
|
||||
$isTask = $task instanceof TaskInterface;
|
||||
$isCollection = $task instanceof NestedCollectionInterface;
|
||||
|
||||
// If the task implements CompletionInterface, ensure
|
||||
// that its 'complete' method is called when the application
|
||||
// terminates -- but only if its 'run' method is called
|
||||
// first. If the task is added to a collection, then the
|
||||
// task will be unwrapped via its `original` method, and
|
||||
// it will be re-wrapped with a new completion wrapper for
|
||||
// its new collection.
|
||||
if ($task instanceof CompletionInterface) {
|
||||
$task = new CompletionWrapper(Temporary::getCollection(), $task);
|
||||
}
|
||||
|
||||
// If we are in simulated mode, then wrap any task in
|
||||
// a TaskSimulator.
|
||||
if ($isTask && !$isCollection && ($this->isSimulated())) {
|
||||
$task = new \Robo\Task\Simulator($task, $args);
|
||||
$task->inflect($this);
|
||||
}
|
||||
|
||||
return $task;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if there are any setter methods defined in configuration
|
||||
* for this task.
|
||||
*/
|
||||
protected function configureTask($taskClass, $task)
|
||||
{
|
||||
$taskClass = static::configClassIdentifier($taskClass);
|
||||
$configurationApplier = new ConfigForSetters($this->getConfig(), $taskClass, 'task.');
|
||||
$configurationApplier->apply($task, 'settings');
|
||||
|
||||
// TODO: If we counted each instance of $taskClass that was called from
|
||||
// this builder, then we could also apply configuration from
|
||||
// "task.{$taskClass}[$N].settings"
|
||||
|
||||
// TODO: If the builder knew what the current command name was,
|
||||
// then we could also search for task configuration under
|
||||
// command-specific keys such as "command.{$commandname}.task.{$taskClass}.settings".
|
||||
}
|
||||
|
||||
/**
|
||||
* When we run the collection builder, run everything in the collection.
|
||||
*
|
||||
* @return \Robo\Result
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
$this->startTimer();
|
||||
$result = $this->runTasks();
|
||||
$this->stopTimer();
|
||||
$result['time'] = $this->getExecutionTime();
|
||||
$result->mergeData($this->getState()->getData());
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* If there is a single task, run it; if there is a collection, run
|
||||
* all of its tasks.
|
||||
*
|
||||
* @return \Robo\Result
|
||||
*/
|
||||
protected function runTasks()
|
||||
{
|
||||
if (!$this->collection && $this->currentTask) {
|
||||
$result = $this->currentTask->run();
|
||||
return Result::ensureResult($this->currentTask, $result);
|
||||
}
|
||||
return $this->getCollection()->run();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getCommand()
|
||||
{
|
||||
if (!$this->collection && $this->currentTask) {
|
||||
$task = $this->currentTask;
|
||||
$task = ($task instanceof WrappedTaskInterface) ? $task->original() : $task;
|
||||
if ($task instanceof CommandInterface) {
|
||||
return $task->getCommand();
|
||||
}
|
||||
}
|
||||
|
||||
return $this->getCollection()->getCommand();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Robo\Collection\Collection
|
||||
*/
|
||||
public function original()
|
||||
{
|
||||
return $this->getCollection();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the collection of tasks associated with this builder.
|
||||
*
|
||||
* @return CollectionInterface
|
||||
*/
|
||||
public function getCollection()
|
||||
{
|
||||
if (!isset($this->collection)) {
|
||||
$this->collection = new Collection();
|
||||
$this->collection->inflect($this);
|
||||
$this->collection->setState($this->getState());
|
||||
$this->collection->setProgressBarAutoDisplayInterval($this->getConfig()->get(Config::PROGRESS_BAR_AUTO_DISPLAY_INTERVAL));
|
||||
|
||||
if (isset($this->currentTask)) {
|
||||
$this->collection->add($this->currentTask);
|
||||
}
|
||||
}
|
||||
return $this->collection;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
<?php
|
||||
namespace Robo\Collection;
|
||||
|
||||
use Psr\Log\LogLevel;
|
||||
use Robo\Contract\TaskInterface;
|
||||
|
||||
interface CollectionInterface extends NestedCollectionInterface
|
||||
{
|
||||
/**
|
||||
* Unnamed tasks are assigned an arbitrary numeric index
|
||||
* in the task list. Any numeric value may be used, but the
|
||||
* UNNAMEDTASK constant is recommended for clarity.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
const UNNAMEDTASK = 0;
|
||||
|
||||
/**
|
||||
* Add a task or a list of tasks to our task collection. Each task
|
||||
* will run via its 'run()' method once (and if) all of the tasks
|
||||
* added before it complete successfully. If the task also implements
|
||||
* RollbackInterface, then it will be rolled back via its 'rollback()'
|
||||
* method ONLY if its 'run()' method completes successfully, and some
|
||||
* task added after it fails.
|
||||
*
|
||||
* @param TaskInterface $task
|
||||
* The task to add to our collection.
|
||||
* @param int|string $name
|
||||
* An optional name for the task -- missing or UNNAMEDTASK for unnamed tasks.
|
||||
* Names are used for positioning before and after tasks.
|
||||
*
|
||||
* @return CollectionInterface
|
||||
*/
|
||||
public function add(TaskInterface $task, $name = self::UNNAMEDTASK);
|
||||
|
||||
/**
|
||||
* Add arbitrary code to execute as a task.
|
||||
*
|
||||
* @param callable $code Code to execute as a task
|
||||
* @param int|string $name
|
||||
* An optional name for the task -- missing or UNNAMEDTASK for unnamed tasks.
|
||||
* Names are used for positioning before and after tasks.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function addCode(callable $code, $name = self::UNNAMEDTASK);
|
||||
|
||||
/**
|
||||
* Add arbitrary code that will be called once for every item in the
|
||||
* provided array or iterable object. If the function result of the
|
||||
* provided callback is a TaskInterface or Collection, then it will be
|
||||
* executed.
|
||||
*
|
||||
* @param CollectionInterface|array $iterable A collection of things to iterate
|
||||
* @param $code $code A callback function to call for each item in the collection.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function addIterable($iterable, callable $code);
|
||||
|
||||
/**
|
||||
* Add a rollback task to our task collection. A rollback task
|
||||
* will execute ONLY if all of the tasks added before it complete
|
||||
* successfully, AND some task added after it fails.
|
||||
*
|
||||
* @param TaskInterface $rollbackTask
|
||||
* The rollback task to add. Note that the 'run()' method of the
|
||||
* task executes, not its 'rollback()' method. To use the 'rollback()'
|
||||
* method, add the task via 'Collection::add()' instead.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function rollback(TaskInterface $rollbackTask);
|
||||
|
||||
/**
|
||||
* Add arbitrary code to execute as a rollback.
|
||||
*
|
||||
* @param callable $rollbackTask Code to execute during rollback processing
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function rollbackCode(callable $rollbackTask);
|
||||
|
||||
/**
|
||||
* Add a completion task to our task collection. A completion task
|
||||
* will execute EITHER after all tasks succeed, OR immediatley after
|
||||
* any task fails. Completion tasks never cause errors to be returned
|
||||
* from Collection::run(), even if they fail.
|
||||
*
|
||||
* @param TaskInterface $completionTask
|
||||
* The completion task to add. Note that the 'run()' method of the
|
||||
* task executes, just as if the task was added normally.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function completion(TaskInterface $completionTask);
|
||||
|
||||
/**
|
||||
* Add arbitrary code to execute as a completion.
|
||||
*
|
||||
* @param callable $completionTask Code to execute after collection completes
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function completionCode(callable $completionTask);
|
||||
|
||||
/**
|
||||
* Add a task before an existing named task.
|
||||
*
|
||||
* @param string $name
|
||||
* The name of the task to insert before. The named task MUST exist.
|
||||
* @param callable|TaskInterface $task
|
||||
* The task to add.
|
||||
* @param int|string $nameOfTaskToAdd
|
||||
* The name of the task to add. If not provided, will be associated
|
||||
* with the named task it was added before.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function before($name, $task, $nameOfTaskToAdd = self::UNNAMEDTASK);
|
||||
|
||||
/**
|
||||
* Add a task after an existing named task.
|
||||
*
|
||||
* @param string $name
|
||||
* The name of the task to insert before. The named task MUST exist.
|
||||
* @param callable|TaskInterface $task
|
||||
* The task to add.
|
||||
* @param int|string $nameOfTaskToAdd
|
||||
* The name of the task to add. If not provided, will be associated
|
||||
* with the named task it was added after.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function after($name, $task, $nameOfTaskToAdd = self::UNNAMEDTASK);
|
||||
|
||||
/**
|
||||
* Print a progress message after Collection::run() has executed
|
||||
* all of the tasks that were added prior to the point when this
|
||||
* method was called. If one of the previous tasks fail, then this
|
||||
* message will not be printed.
|
||||
*
|
||||
* @param string $text Message to print.
|
||||
* @param array $context Extra context data for use by the logger. Note
|
||||
* that the data from the collection state is merged with the provided context.
|
||||
* @param \Psr\Log\LogLevel|string $level The log level to print the information at. Default is NOTICE.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function progressMessage($text, $context = [], $level = LogLevel::NOTICE);
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
namespace Robo\Collection;
|
||||
|
||||
use Consolidation\AnnotatedCommand\Hooks\ProcessResultInterface;
|
||||
use Consolidation\AnnotatedCommand\CommandData;
|
||||
use Robo\Contract\TaskInterface;
|
||||
use Robo\Result;
|
||||
|
||||
/**
|
||||
* The collection process hook is added to the annotation command
|
||||
* hook manager in Runner::configureContainer(). This hook will be
|
||||
* called every time a command runs. If the command result is a
|
||||
* \Robo\Contract\TaskInterface (in particular, \Robo\Collection\Collection),
|
||||
* then we run the collection, and return the result. We ignore results
|
||||
* of any other type.
|
||||
*/
|
||||
class CollectionProcessHook implements ProcessResultInterface
|
||||
{
|
||||
/**
|
||||
* @param \Robo\Result|\Robo\Contract\TaskInterface $result
|
||||
* @param \Consolidation\AnnotatedCommand\CommandData $commandData
|
||||
*
|
||||
* @return null|\Robo\Result
|
||||
*/
|
||||
public function process($result, CommandData $commandData)
|
||||
{
|
||||
if ($result instanceof TaskInterface) {
|
||||
try {
|
||||
return $result->run();
|
||||
} catch (\Exception $e) {
|
||||
return Result::fromException($result, $e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
106
core/lib/composer/vendor/consolidation/robo/scenarios/symfony2/src/Collection/CompletionWrapper.php
vendored
Normal file
106
core/lib/composer/vendor/consolidation/robo/scenarios/symfony2/src/Collection/CompletionWrapper.php
vendored
Normal file
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
namespace Robo\Collection;
|
||||
|
||||
use Robo\Task\BaseTask;
|
||||
use Robo\Contract\TaskInterface;
|
||||
use Robo\Contract\RollbackInterface;
|
||||
use Robo\Contract\CompletionInterface;
|
||||
use Robo\Contract\WrappedTaskInterface;
|
||||
|
||||
/**
|
||||
* Creates a task wrapper that will manage rollback and collection
|
||||
* management to a task when it runs. Tasks are automatically
|
||||
* wrapped in a CompletionWrapper when added to a task collection.
|
||||
*
|
||||
* Clients may need to wrap their task in a CompletionWrapper if it
|
||||
* creates temporary objects.
|
||||
*
|
||||
* @see \Robo\Task\Filesystem\loadTasks::taskTmpDir
|
||||
*/
|
||||
class CompletionWrapper extends BaseTask implements WrappedTaskInterface
|
||||
{
|
||||
/**
|
||||
* @var \Robo\Collection\Collection
|
||||
*/
|
||||
private $collection;
|
||||
|
||||
/**
|
||||
* @var \Robo\Contract\TaskInterface
|
||||
*/
|
||||
private $task;
|
||||
|
||||
/**
|
||||
* @var NULL|\Robo\Contract\TaskInterface
|
||||
*/
|
||||
private $rollbackTask;
|
||||
|
||||
/**
|
||||
* Create a CompletionWrapper.
|
||||
*
|
||||
* Temporary tasks are always wrapped in a CompletionWrapper, as are
|
||||
* any tasks that are added to a collection. If a temporary task
|
||||
* is added to a collection, then it is first unwrapped from its
|
||||
* CompletionWrapper (via its original() method), and then added to a
|
||||
* new CompletionWrapper for the collection it is added to.
|
||||
*
|
||||
* In this way, when the CompletionWrapper is finally executed, the
|
||||
* task's rollback and completion handlers will be registered on
|
||||
* whichever collection it was registered on.
|
||||
*
|
||||
* @todo Why not CollectionInterface the type of the $collection argument?
|
||||
*
|
||||
* @param \Robo\Collection\Collection $collection
|
||||
* @param \Robo\Contract\TaskInterface $task
|
||||
* @param \Robo\Contract\TaskInterface|NULL $rollbackTask
|
||||
*/
|
||||
public function __construct(Collection $collection, TaskInterface $task, TaskInterface $rollbackTask = null)
|
||||
{
|
||||
$this->collection = $collection;
|
||||
$this->task = ($task instanceof WrappedTaskInterface) ? $task->original() : $task;
|
||||
$this->rollbackTask = $rollbackTask;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function original()
|
||||
{
|
||||
return $this->task;
|
||||
}
|
||||
|
||||
/**
|
||||
* Before running this task, register its rollback and completion
|
||||
* handlers on its collection. The reason this class exists is to
|
||||
* defer registration of rollback and completion tasks until 'run()' time.
|
||||
*
|
||||
* @return \Robo\Result
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
if ($this->rollbackTask) {
|
||||
$this->collection->registerRollback($this->rollbackTask);
|
||||
}
|
||||
if ($this->task instanceof RollbackInterface) {
|
||||
$this->collection->registerRollback(new CallableTask([$this->task, 'rollback'], $this->task));
|
||||
}
|
||||
if ($this->task instanceof CompletionInterface) {
|
||||
$this->collection->registerCompletion(new CallableTask([$this->task, 'complete'], $this->task));
|
||||
}
|
||||
|
||||
return $this->task->run();
|
||||
}
|
||||
|
||||
/**
|
||||
* Make this wrapper object act like the class it wraps.
|
||||
*
|
||||
* @param string $function
|
||||
* @param array $args
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function __call($function, $args)
|
||||
{
|
||||
return call_user_func_array(array($this->task, $function), $args);
|
||||
}
|
||||
}
|
||||
116
core/lib/composer/vendor/consolidation/robo/scenarios/symfony2/src/Collection/Element.php
vendored
Normal file
116
core/lib/composer/vendor/consolidation/robo/scenarios/symfony2/src/Collection/Element.php
vendored
Normal file
@@ -0,0 +1,116 @@
|
||||
<?php
|
||||
|
||||
namespace Robo\Collection;
|
||||
|
||||
use Robo\Contract\TaskInterface;
|
||||
use Robo\Contract\WrappedTaskInterface;
|
||||
use Robo\Contract\ProgressIndicatorAwareInterface;
|
||||
|
||||
/**
|
||||
* One element in a collection. Each element consists of a task
|
||||
* all of its before tasks, and all of its after tasks.
|
||||
*
|
||||
* This class is internal to Collection; it should not be used directly.
|
||||
*/
|
||||
class Element
|
||||
{
|
||||
/**
|
||||
* @var \Robo\Contract\TaskInterface
|
||||
*/
|
||||
protected $task;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $before = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $after = [];
|
||||
|
||||
public function __construct(TaskInterface $task)
|
||||
{
|
||||
$this->task = $task;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $before
|
||||
* @param string $name
|
||||
*/
|
||||
public function before($before, $name)
|
||||
{
|
||||
if ($name) {
|
||||
$this->before[$name] = $before;
|
||||
} else {
|
||||
$this->before[] = $before;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $after
|
||||
* @param string $name
|
||||
*/
|
||||
public function after($after, $name)
|
||||
{
|
||||
if ($name) {
|
||||
$this->after[$name] = $after;
|
||||
} else {
|
||||
$this->after[] = $after;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getBefore()
|
||||
{
|
||||
return $this->before;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getAfter()
|
||||
{
|
||||
return $this->after;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Robo\Contract\TaskInterface
|
||||
*/
|
||||
public function getTask()
|
||||
{
|
||||
return $this->task;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getTaskList()
|
||||
{
|
||||
return array_merge($this->getBefore(), [$this->getTask()], $this->getAfter());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function progressIndicatorSteps()
|
||||
{
|
||||
$steps = 0;
|
||||
foreach ($this->getTaskList() as $task) {
|
||||
if ($task instanceof WrappedTaskInterface) {
|
||||
$task = $task->original();
|
||||
}
|
||||
// If the task is a ProgressIndicatorAwareInterface, then it
|
||||
// will advance the progress indicator a number of times.
|
||||
if ($task instanceof ProgressIndicatorAwareInterface) {
|
||||
$steps += $task->progressIndicatorSteps();
|
||||
}
|
||||
// We also advance the progress indicator once regardless
|
||||
// of whether it is progress-indicator aware or not.
|
||||
$steps++;
|
||||
}
|
||||
return $steps;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
namespace Robo\Collection;
|
||||
|
||||
interface NestedCollectionInterface
|
||||
{
|
||||
/**
|
||||
* @param \Robo\Collection\NestedCollectionInterface $parentCollection
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setParentCollection(NestedCollectionInterface $parentCollection);
|
||||
}
|
||||
196
core/lib/composer/vendor/consolidation/robo/scenarios/symfony2/src/Collection/TaskForEach.php
vendored
Normal file
196
core/lib/composer/vendor/consolidation/robo/scenarios/symfony2/src/Collection/TaskForEach.php
vendored
Normal file
@@ -0,0 +1,196 @@
|
||||
<?php
|
||||
namespace Robo\Collection;
|
||||
|
||||
use Robo\Result;
|
||||
use Robo\TaskInfo;
|
||||
use Robo\Task\BaseTask;
|
||||
use Robo\Contract\BuilderAwareInterface;
|
||||
use Robo\Common\BuilderAwareTrait;
|
||||
|
||||
/**
|
||||
* Creates a task wrapper that converts any Callable into an
|
||||
* object that will execute the callback once for each item in the
|
||||
* provided collection.
|
||||
*
|
||||
* It is not necessary to use this class directly; Collection::addIterable
|
||||
* will automatically create one when it is called.
|
||||
*/
|
||||
class TaskForEach extends BaseTask implements NestedCollectionInterface, BuilderAwareInterface
|
||||
{
|
||||
use BuilderAwareTrait;
|
||||
|
||||
/**
|
||||
* @var callable[]
|
||||
*/
|
||||
protected $functionStack = [];
|
||||
|
||||
/**
|
||||
* @var callable[]
|
||||
*/
|
||||
protected $countingStack = [];
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $message;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $context = [];
|
||||
|
||||
protected $iterable;
|
||||
|
||||
/**
|
||||
* @var \Robo\Collection\NestedCollectionInterface
|
||||
*/
|
||||
protected $parentCollection;
|
||||
|
||||
public function __construct($iterable)
|
||||
{
|
||||
$this->iterable = $iterable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $message
|
||||
* @param array $context
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function iterationMessage($message, $context = [])
|
||||
{
|
||||
$this->message = $message;
|
||||
$this->context = $context + ['name' => 'Progress'];
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int|string $key
|
||||
* @param mixed $value
|
||||
*/
|
||||
protected function showIterationMessage($key, $value)
|
||||
{
|
||||
if ($this->message) {
|
||||
$context = ['key' => $key, 'value' => $value];
|
||||
$context += $this->context;
|
||||
$context += TaskInfo::getTaskContext($this);
|
||||
$this->printTaskInfo($this->message, $context);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param callable $fn
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function withEachKeyValueCall(callable $fn)
|
||||
{
|
||||
$this->functionStack[] = $fn;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param callable $fn
|
||||
*
|
||||
* @return \Robo\Collection\TaskForEach
|
||||
*/
|
||||
public function call(callable $fn)
|
||||
{
|
||||
return $this->withEachKeyValueCall(
|
||||
function ($key, $value) use ($fn) {
|
||||
return call_user_func($fn, $value);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param callable $fn
|
||||
*
|
||||
* @return \Robo\Collection\TaskForEach
|
||||
*/
|
||||
public function withBuilder(callable $fn)
|
||||
{
|
||||
$this->countingStack[] =
|
||||
function ($key, $value) use ($fn) {
|
||||
// Create a new builder for every iteration
|
||||
$builder = $this->collectionBuilder();
|
||||
// The user function should build task operations using
|
||||
// the $key / $value parameters; we will call run() on
|
||||
// the builder thus constructed.
|
||||
call_user_func($fn, $builder, $key, $value);
|
||||
return $builder->getCollection()->progressIndicatorSteps();
|
||||
};
|
||||
return $this->withEachKeyValueCall(
|
||||
function ($key, $value) use ($fn) {
|
||||
// Create a new builder for every iteration
|
||||
$builder = $this->collectionBuilder()
|
||||
->setParentCollection($this->parentCollection);
|
||||
// The user function should build task operations using
|
||||
// the $key / $value parameters; we will call run() on
|
||||
// the builder thus constructed.
|
||||
call_user_func($fn, $builder, $key, $value);
|
||||
return $builder->run();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setParentCollection(NestedCollectionInterface $parentCollection)
|
||||
{
|
||||
$this->parentCollection = $parentCollection;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function progressIndicatorSteps()
|
||||
{
|
||||
$multiplier = count($this->functionStack);
|
||||
if (!empty($this->countingStack)) {
|
||||
$value = reset($this->iterable);
|
||||
$key = key($this->iterable);
|
||||
foreach ($this->countingStack as $fn) {
|
||||
$multiplier += call_user_func($fn, $key, $value);
|
||||
}
|
||||
}
|
||||
return count($this->iterable) * $multiplier;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
$finalResult = Result::success($this);
|
||||
$this->startProgressIndicator();
|
||||
foreach ($this->iterable as $key => $value) {
|
||||
$this->showIterationMessage($key, $value);
|
||||
try {
|
||||
foreach ($this->functionStack as $fn) {
|
||||
$result = call_user_func($fn, $key, $value);
|
||||
$this->advanceProgressIndicator();
|
||||
if (!isset($result)) {
|
||||
$result = Result::success($this);
|
||||
}
|
||||
// If the function returns a result, it must either return
|
||||
// a \Robo\Result or an exit code. In the later case, we
|
||||
// convert it to a \Robo\Result.
|
||||
if (!$result instanceof Result) {
|
||||
$result = new Result($this, $result);
|
||||
}
|
||||
if (!$result->wasSuccessful()) {
|
||||
return $result;
|
||||
}
|
||||
$finalResult = $result->merge($finalResult);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
return Result::fromException($result, $e);
|
||||
}
|
||||
}
|
||||
$this->stopProgressIndicator();
|
||||
return $finalResult;
|
||||
}
|
||||
}
|
||||
57
core/lib/composer/vendor/consolidation/robo/scenarios/symfony2/src/Collection/Temporary.php
vendored
Normal file
57
core/lib/composer/vendor/consolidation/robo/scenarios/symfony2/src/Collection/Temporary.php
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
namespace Robo\Collection;
|
||||
|
||||
/**
|
||||
* The temporary collection keeps track of the global collection of
|
||||
* temporary cleanup tasks in instances where temporary-generating
|
||||
* tasks are executed directly via their run() method, rather than
|
||||
* as part of a collection.
|
||||
*
|
||||
* In general, temporary-generating tasks should always be run in
|
||||
* a collection, as the cleanup functions registered with the
|
||||
* Temporary collection will not run until requested.
|
||||
*
|
||||
* Since the results could be undefined if cleanup functions were called
|
||||
* at arbitrary times during a program's execution, cleanup should only
|
||||
* be done immeidately prior to program termination, when there is no
|
||||
* danger of cleaning up after some unrelated task.
|
||||
*
|
||||
* An application need never use Temporary directly, save to
|
||||
* call Temporary::wrap() inside loadTasks or loadShortcuts, and
|
||||
* to call Temporary::complete() immediately prior to terminating.
|
||||
* This is recommended, but not required; this function will be
|
||||
* registered as a shutdown function, and called on termination.
|
||||
*/
|
||||
class Temporary
|
||||
{
|
||||
private static $collection;
|
||||
|
||||
/**
|
||||
* Provides direct access to the collection of temporaries, if necessary.
|
||||
*/
|
||||
public static function getCollection()
|
||||
{
|
||||
if (!static::$collection) {
|
||||
static::$collection = \Robo\Robo::getContainer()->get('collection');
|
||||
register_shutdown_function(function () {
|
||||
static::complete();
|
||||
});
|
||||
}
|
||||
|
||||
return static::$collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call the complete method of all of the registered objects.
|
||||
*/
|
||||
public static function complete()
|
||||
{
|
||||
// Run the collection of tasks. This will also run the
|
||||
// completion tasks.
|
||||
$collection = static::getCollection();
|
||||
$collection->run();
|
||||
// Make sure that our completion functions do not run twice.
|
||||
$collection->reset();
|
||||
}
|
||||
}
|
||||
17
core/lib/composer/vendor/consolidation/robo/scenarios/symfony2/src/Collection/loadTasks.php
vendored
Normal file
17
core/lib/composer/vendor/consolidation/robo/scenarios/symfony2/src/Collection/loadTasks.php
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
namespace Robo\Collection;
|
||||
|
||||
trait loadTasks
|
||||
{
|
||||
/**
|
||||
* Run a callback function on each item in a collection
|
||||
*
|
||||
* @param array $collection
|
||||
*
|
||||
* @return \Robo\Collection\TaskForEach
|
||||
*/
|
||||
protected function taskForEach($collection)
|
||||
{
|
||||
return $this->task(TaskForEach::class, $collection);
|
||||
}
|
||||
}
|
||||
45
core/lib/composer/vendor/consolidation/robo/scenarios/symfony2/src/Common/BuilderAwareTrait.php
vendored
Normal file
45
core/lib/composer/vendor/consolidation/robo/scenarios/symfony2/src/Common/BuilderAwareTrait.php
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace Robo\Common;
|
||||
|
||||
use Robo\Collection\CollectionBuilder;
|
||||
|
||||
trait BuilderAwareTrait
|
||||
{
|
||||
/**
|
||||
* @var \Robo\Collection\CollectionBuilder
|
||||
*/
|
||||
protected $builder;
|
||||
|
||||
/**
|
||||
* @see \Robo\Contract\BuilderAwareInterface::setBuilder()
|
||||
*
|
||||
* @param \Robo\Collection\CollectionBuilder $builder
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setBuilder(CollectionBuilder $builder)
|
||||
{
|
||||
$this->builder = $builder;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see \Robo\Contract\BuilderAwareInterface::getBuilder()
|
||||
*
|
||||
* @return \Robo\Collection\CollectionBuilder
|
||||
*/
|
||||
public function getBuilder()
|
||||
{
|
||||
return $this->builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Robo\Collection\CollectionBuilder
|
||||
*/
|
||||
protected function collectionBuilder()
|
||||
{
|
||||
return $this->getBuilder()->newBuilder();
|
||||
}
|
||||
}
|
||||
130
core/lib/composer/vendor/consolidation/robo/scenarios/symfony2/src/Common/CommandArguments.php
vendored
Normal file
130
core/lib/composer/vendor/consolidation/robo/scenarios/symfony2/src/Common/CommandArguments.php
vendored
Normal file
@@ -0,0 +1,130 @@
|
||||
<?php
|
||||
namespace Robo\Common;
|
||||
|
||||
use Robo\Common\ProcessUtils;
|
||||
|
||||
/**
|
||||
* Use this to add arguments and options to the $arguments property.
|
||||
*/
|
||||
trait CommandArguments
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $arguments = '';
|
||||
|
||||
/**
|
||||
* Pass argument to executable. Its value will be automatically escaped.
|
||||
*
|
||||
* @param string $arg
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function arg($arg)
|
||||
{
|
||||
return $this->args($arg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pass methods parameters as arguments to executable. Argument values
|
||||
* are automatically escaped.
|
||||
*
|
||||
* @param string|string[] $args
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function args($args)
|
||||
{
|
||||
if (!is_array($args)) {
|
||||
$args = func_get_args();
|
||||
}
|
||||
$this->arguments .= ' ' . implode(' ', array_map('static::escape', $args));
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pass the provided string in its raw (as provided) form as an argument to executable.
|
||||
*
|
||||
* @param string $arg
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function rawArg($arg)
|
||||
{
|
||||
$this->arguments .= " $arg";
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape the provided value, unless it contains only alphanumeric
|
||||
* plus a few other basic characters.
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function escape($value)
|
||||
{
|
||||
if (preg_match('/^[a-zA-Z0-9\/\.@~_-]+$/', $value)) {
|
||||
return $value;
|
||||
}
|
||||
return ProcessUtils::escapeArgument($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pass option to executable. Options are prefixed with `--` , value can be provided in second parameter.
|
||||
* Option values are automatically escaped.
|
||||
*
|
||||
* @param string $option
|
||||
* @param string $value
|
||||
* @param string $separator
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function option($option, $value = null, $separator = ' ')
|
||||
{
|
||||
if ($option !== null and strpos($option, '-') !== 0) {
|
||||
$option = "--$option";
|
||||
}
|
||||
$this->arguments .= null == $option ? '' : " " . $option;
|
||||
$this->arguments .= null == $value ? '' : $separator . static::escape($value);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pass multiple options to executable. The associative array contains
|
||||
* the key:value pairs that become `--key value`, for each item in the array.
|
||||
* Values are automatically escaped.
|
||||
*/
|
||||
public function options(array $options, $separator = ' ')
|
||||
{
|
||||
foreach ($options as $option => $value) {
|
||||
$this->option($option, $value, $separator);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pass an option with multiple values to executable. Value can be a string or array.
|
||||
* Option values are automatically escaped.
|
||||
*
|
||||
* @param string $option
|
||||
* @param string|array $value
|
||||
* @param string $separator
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function optionList($option, $value = array(), $separator = ' ')
|
||||
{
|
||||
if (is_array($value)) {
|
||||
foreach ($value as $item) {
|
||||
$this->optionList($option, $item, $separator);
|
||||
}
|
||||
} else {
|
||||
$this->option($option, $value, $separator);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
30
core/lib/composer/vendor/consolidation/robo/scenarios/symfony2/src/Common/CommandReceiver.php
vendored
Normal file
30
core/lib/composer/vendor/consolidation/robo/scenarios/symfony2/src/Common/CommandReceiver.php
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
namespace Robo\Common;
|
||||
|
||||
use Robo\Contract\CommandInterface;
|
||||
use Robo\Exception\TaskException;
|
||||
|
||||
/**
|
||||
* This task can receive commands from task implementing CommandInterface.
|
||||
*/
|
||||
trait CommandReceiver
|
||||
{
|
||||
/**
|
||||
* @param string|\Robo\Contract\CommandInterface $command
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws \Robo\Exception\TaskException
|
||||
*/
|
||||
protected function receiveCommand($command)
|
||||
{
|
||||
if (!is_object($command)) {
|
||||
return $command;
|
||||
}
|
||||
if ($command instanceof CommandInterface) {
|
||||
return $command->getCommand();
|
||||
} else {
|
||||
throw new TaskException($this, get_class($command) . " does not implement CommandInterface, so can't be passed into this task");
|
||||
}
|
||||
}
|
||||
}
|
||||
109
core/lib/composer/vendor/consolidation/robo/scenarios/symfony2/src/Common/ConfigAwareTrait.php
vendored
Normal file
109
core/lib/composer/vendor/consolidation/robo/scenarios/symfony2/src/Common/ConfigAwareTrait.php
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
<?php
|
||||
|
||||
namespace Robo\Common;
|
||||
|
||||
use Robo\Robo;
|
||||
use Consolidation\Config\ConfigInterface;
|
||||
|
||||
trait ConfigAwareTrait
|
||||
{
|
||||
/**
|
||||
* @var ConfigInterface
|
||||
*/
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* Set the config management object.
|
||||
*
|
||||
* @param ConfigInterface $config
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @see \Robo\Contract\ConfigAwareInterface::setConfig()
|
||||
*/
|
||||
public function setConfig(ConfigInterface $config)
|
||||
{
|
||||
$this->config = $config;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the config management object.
|
||||
*
|
||||
* @return ConfigInterface
|
||||
*
|
||||
* @see \Robo\Contract\ConfigAwareInterface::getConfig()
|
||||
*/
|
||||
public function getConfig()
|
||||
{
|
||||
return $this->config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Any class that uses ConfigAwareTrait SHOULD override this method
|
||||
* , and define a prefix for its configuration items. This is usually
|
||||
* done in a base class. When used, this method should return a string
|
||||
* that ends with a "."; see BaseTask::configPrefix().
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected static function configPrefix()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
protected static function configClassIdentifier($classname)
|
||||
{
|
||||
$configIdentifier = strtr($classname, '\\', '.');
|
||||
$configIdentifier = preg_replace('#^(.*\.Task\.|\.)#', '', $configIdentifier);
|
||||
|
||||
return $configIdentifier;
|
||||
}
|
||||
|
||||
protected static function configPostfix()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private static function getClassKey($key)
|
||||
{
|
||||
$configPrefix = static::configPrefix(); // task.
|
||||
$configClass = static::configClassIdentifier(get_called_class()); // PARTIAL_NAMESPACE.CLASSNAME
|
||||
$configPostFix = static::configPostfix(); // .settings
|
||||
|
||||
return sprintf('%s%s%s.%s', $configPrefix, $configClass, $configPostFix, $key);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @param Config|null $config
|
||||
*/
|
||||
public static function configure($key, $value, $config = null)
|
||||
{
|
||||
if (!$config) {
|
||||
$config = Robo::config();
|
||||
}
|
||||
$config->setDefault(static::getClassKey($key), $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @param mixed|null $default
|
||||
*
|
||||
* @return mixed|null
|
||||
*/
|
||||
protected function getConfigValue($key, $default = null)
|
||||
{
|
||||
if (!$this->getConfig()) {
|
||||
return $default;
|
||||
}
|
||||
return $this->getConfig()->get(static::getClassKey($key), $default);
|
||||
}
|
||||
}
|
||||
45
core/lib/composer/vendor/consolidation/robo/scenarios/symfony2/src/Common/DynamicParams.php
vendored
Normal file
45
core/lib/composer/vendor/consolidation/robo/scenarios/symfony2/src/Common/DynamicParams.php
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
namespace Robo\Common;
|
||||
|
||||
/**
|
||||
* Simplifies generating of configuration chanined methods.
|
||||
* You can only define configuration properties and use magic methods to set them.
|
||||
* Methods will be named the same way as properties.
|
||||
* * Boolean properties are switched on/off if no values is provided.
|
||||
* * Array properties can accept non-array values, in this case value will be appended to array.
|
||||
* You should also define phpdoc for methods.
|
||||
*/
|
||||
trait DynamicParams
|
||||
{
|
||||
/**
|
||||
* @param string $property
|
||||
* @param array $args
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function __call($property, $args)
|
||||
{
|
||||
if (!property_exists($this, $property)) {
|
||||
throw new \RuntimeException("Property $property in task ".get_class($this).' does not exists');
|
||||
}
|
||||
|
||||
// toggle boolean values
|
||||
if (!isset($args[0]) and (is_bool($this->$property))) {
|
||||
$this->$property = !$this->$property;
|
||||
return $this;
|
||||
}
|
||||
|
||||
// append item to array
|
||||
if (is_array($this->$property)) {
|
||||
if (is_array($args[0])) {
|
||||
$this->$property = $args[0];
|
||||
} else {
|
||||
array_push($this->$property, $args[0]);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
$this->$property = $args[0];
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
148
core/lib/composer/vendor/consolidation/robo/scenarios/symfony2/src/Common/ExecCommand.php
vendored
Normal file
148
core/lib/composer/vendor/consolidation/robo/scenarios/symfony2/src/Common/ExecCommand.php
vendored
Normal file
@@ -0,0 +1,148 @@
|
||||
<?php
|
||||
namespace Robo\Common;
|
||||
|
||||
use Robo\Result;
|
||||
use Symfony\Component\Process\ExecutableFinder;
|
||||
use Symfony\Component\Process\Process;
|
||||
|
||||
/**
|
||||
* This task is supposed to be executed as shell command.
|
||||
* You can specify working directory and if output is printed.
|
||||
*/
|
||||
trait ExecCommand
|
||||
{
|
||||
use ExecTrait;
|
||||
|
||||
/**
|
||||
* @var \Robo\Common\TimeKeeper
|
||||
*/
|
||||
protected $execTimer;
|
||||
|
||||
/**
|
||||
* @return \Robo\Common\TimeKeeper
|
||||
*/
|
||||
protected function getExecTimer()
|
||||
{
|
||||
if (!isset($this->execTimer)) {
|
||||
$this->execTimer = new TimeKeeper();
|
||||
}
|
||||
return $this->execTimer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Look for a "{$cmd}.phar" in the current working
|
||||
* directory; return a string to exec it if it is
|
||||
* found. Otherwise, look for an executable command
|
||||
* of the same name via findExecutable.
|
||||
*
|
||||
* @param string $cmd
|
||||
*
|
||||
* @return bool|string
|
||||
*/
|
||||
protected function findExecutablePhar($cmd)
|
||||
{
|
||||
if (file_exists("{$cmd}.phar")) {
|
||||
return "php {$cmd}.phar";
|
||||
}
|
||||
return $this->findExecutable($cmd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the best path to the executable program
|
||||
* with the provided name. Favor vendor/bin in the
|
||||
* current project. If not found there, use
|
||||
* whatever is on the $PATH.
|
||||
*
|
||||
* @param string $cmd
|
||||
*
|
||||
* @return bool|string
|
||||
*/
|
||||
protected function findExecutable($cmd)
|
||||
{
|
||||
$pathToCmd = $this->searchForExecutable($cmd);
|
||||
if ($pathToCmd) {
|
||||
return $this->useCallOnWindows($pathToCmd);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $cmd
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function searchForExecutable($cmd)
|
||||
{
|
||||
$projectBin = $this->findProjectBin();
|
||||
|
||||
$localComposerInstallation = $projectBin . DIRECTORY_SEPARATOR . $cmd;
|
||||
if (file_exists($localComposerInstallation)) {
|
||||
return $localComposerInstallation;
|
||||
}
|
||||
$finder = new ExecutableFinder();
|
||||
return $finder->find($cmd, null, []);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool|string
|
||||
*/
|
||||
protected function findProjectBin()
|
||||
{
|
||||
$cwd = getcwd();
|
||||
$candidates = [ __DIR__ . '/../../vendor/bin', __DIR__ . '/../../bin', $cwd . '/vendor/bin' ];
|
||||
|
||||
// If this project is inside a vendor directory, give highest priority
|
||||
// to that directory.
|
||||
$vendorDirContainingUs = realpath(__DIR__ . '/../../../..');
|
||||
if (is_dir($vendorDirContainingUs) && (basename($vendorDirContainingUs) == 'vendor')) {
|
||||
array_unshift($candidates, $vendorDirContainingUs . '/bin');
|
||||
}
|
||||
|
||||
foreach ($candidates as $dir) {
|
||||
if (is_dir("$dir")) {
|
||||
return realpath($dir);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap Windows executables in 'call' per 7a88757d
|
||||
*
|
||||
* @param string $cmd
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function useCallOnWindows($cmd)
|
||||
{
|
||||
if (defined('PHP_WINDOWS_VERSION_BUILD')) {
|
||||
if (file_exists("{$cmd}.bat")) {
|
||||
$cmd = "{$cmd}.bat";
|
||||
}
|
||||
return "call $cmd";
|
||||
}
|
||||
return $cmd;
|
||||
}
|
||||
|
||||
protected function getCommandDescription()
|
||||
{
|
||||
return $this->process->getCommandLine();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $command
|
||||
*
|
||||
* @return \Robo\Result
|
||||
*/
|
||||
protected function executeCommand($command)
|
||||
{
|
||||
// TODO: Symfony 4 requires that we supply the working directory.
|
||||
$result_data = $this->execute(new Process($command, getcwd()));
|
||||
return new Result(
|
||||
$this,
|
||||
$result_data->getExitCode(),
|
||||
$result_data->getMessage(),
|
||||
$result_data->getData()
|
||||
);
|
||||
}
|
||||
}
|
||||
12
core/lib/composer/vendor/consolidation/robo/scenarios/symfony2/src/Common/ExecOneCommand.php
vendored
Normal file
12
core/lib/composer/vendor/consolidation/robo/scenarios/symfony2/src/Common/ExecOneCommand.php
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
namespace Robo\Common;
|
||||
|
||||
/**
|
||||
* This task specifies exactly one shell command.
|
||||
* It can take additional arguments and options as config parameters.
|
||||
*/
|
||||
trait ExecOneCommand
|
||||
{
|
||||
use ExecCommand;
|
||||
use CommandArguments;
|
||||
}
|
||||
408
core/lib/composer/vendor/consolidation/robo/scenarios/symfony2/src/Common/ExecTrait.php
vendored
Normal file
408
core/lib/composer/vendor/consolidation/robo/scenarios/symfony2/src/Common/ExecTrait.php
vendored
Normal file
@@ -0,0 +1,408 @@
|
||||
<?php
|
||||
|
||||
namespace Robo\Common;
|
||||
|
||||
use Robo\ResultData;
|
||||
use Symfony\Component\Process\Process;
|
||||
|
||||
/**
|
||||
* Class ExecTrait
|
||||
* @package Robo\Common
|
||||
*/
|
||||
trait ExecTrait
|
||||
{
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $background = false;
|
||||
|
||||
/**
|
||||
* @var null|int
|
||||
*/
|
||||
protected $timeout = null;
|
||||
|
||||
/**
|
||||
* @var null|int
|
||||
*/
|
||||
protected $idleTimeout = null;
|
||||
|
||||
/**
|
||||
* @var null|array
|
||||
*/
|
||||
protected $env = null;
|
||||
|
||||
/**
|
||||
* @var Process
|
||||
*/
|
||||
protected $process;
|
||||
|
||||
/**
|
||||
* @var resource|string
|
||||
*/
|
||||
protected $input;
|
||||
|
||||
/**
|
||||
* @var boolean
|
||||
*/
|
||||
protected $interactive = null;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $isPrinted = true;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $isMetadataPrinted = true;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $workingDirectory;
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
abstract public function getCommandDescription();
|
||||
|
||||
/** Typically provided by Timer trait via ProgressIndicatorAwareTrait. */
|
||||
abstract public function startTimer();
|
||||
abstract public function stopTimer();
|
||||
abstract public function getExecutionTime();
|
||||
|
||||
/**
|
||||
* Typically provided by TaskIO Trait.
|
||||
*/
|
||||
abstract public function hideTaskProgress();
|
||||
abstract public function showTaskProgress($inProgress);
|
||||
abstract public function printTaskInfo($text, $context = null);
|
||||
|
||||
/**
|
||||
* Typically provided by VerbosityThresholdTrait.
|
||||
*/
|
||||
abstract public function verbosityMeetsThreshold();
|
||||
abstract public function writeMessage($message);
|
||||
|
||||
/**
|
||||
* Sets $this->interactive() based on posix_isatty().
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function detectInteractive()
|
||||
{
|
||||
// If the caller did not explicity set the 'interactive' mode,
|
||||
// and output should be produced by this task (verbosityMeetsThreshold),
|
||||
// then we will automatically set interactive mode based on whether
|
||||
// or not output was redirected when robo was executed.
|
||||
if (!isset($this->interactive) && function_exists('posix_isatty') && $this->verbosityMeetsThreshold()) {
|
||||
$this->interactive = posix_isatty(STDOUT);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes command in background mode (asynchronously)
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function background($arg = true)
|
||||
{
|
||||
$this->background = $arg;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop command if it runs longer then $timeout in seconds
|
||||
*
|
||||
* @param int $timeout
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function timeout($timeout)
|
||||
{
|
||||
$this->timeout = $timeout;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops command if it does not output something for a while
|
||||
*
|
||||
* @param int $timeout
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function idleTimeout($timeout)
|
||||
{
|
||||
$this->idleTimeout = $timeout;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a single environment variable, or multiple.
|
||||
*/
|
||||
public function env($env, $value = null)
|
||||
{
|
||||
if (!is_array($env)) {
|
||||
$env = [$env => ($value ? $value : true)];
|
||||
}
|
||||
return $this->envVars($env);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the environment variables for the command
|
||||
*
|
||||
* @param array $env
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function envVars(array $env)
|
||||
{
|
||||
$this->env = $env;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pass an input to the process. Can be resource created with fopen() or string
|
||||
*
|
||||
* @param resource|string $input
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setInput($input)
|
||||
{
|
||||
$this->input = $input;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach tty to process for interactive input
|
||||
*
|
||||
* @param $interactive bool
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function interactive($interactive = true)
|
||||
{
|
||||
$this->interactive = $interactive;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Is command printing its output to screen
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getPrinted()
|
||||
{
|
||||
return $this->isPrinted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes working directory of command
|
||||
*
|
||||
* @param string $dir
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function dir($dir)
|
||||
{
|
||||
$this->workingDirectory = $dir;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortcut for setting isPrinted() and isMetadataPrinted() to false.
|
||||
*
|
||||
* @param bool $arg
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function silent($arg)
|
||||
{
|
||||
if (is_bool($arg)) {
|
||||
$this->isPrinted = !$arg;
|
||||
$this->isMetadataPrinted = !$arg;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should command output be printed
|
||||
*
|
||||
* @param bool $arg
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
public function printed($arg)
|
||||
{
|
||||
$this->logger->warning("printed() is deprecated. Please use printOutput().");
|
||||
return $this->printOutput($arg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Should command output be printed
|
||||
*
|
||||
* @param bool $arg
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function printOutput($arg)
|
||||
{
|
||||
if (is_bool($arg)) {
|
||||
$this->isPrinted = $arg;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should command metadata be printed. I,e., command and timer.
|
||||
*
|
||||
* @param bool $arg
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function printMetadata($arg)
|
||||
{
|
||||
if (is_bool($arg)) {
|
||||
$this->isMetadataPrinted = $arg;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Process $process
|
||||
* @param callable $output_callback
|
||||
*
|
||||
* @return \Robo\ResultData
|
||||
*/
|
||||
protected function execute($process, $output_callback = null)
|
||||
{
|
||||
$this->process = $process;
|
||||
|
||||
if (!$output_callback) {
|
||||
$output_callback = function ($type, $buffer) {
|
||||
$progressWasVisible = $this->hideTaskProgress();
|
||||
$this->writeMessage($buffer);
|
||||
$this->showTaskProgress($progressWasVisible);
|
||||
};
|
||||
}
|
||||
|
||||
$this->detectInteractive();
|
||||
|
||||
if ($this->isMetadataPrinted) {
|
||||
$this->printAction();
|
||||
}
|
||||
$this->process->setTimeout($this->timeout);
|
||||
$this->process->setIdleTimeout($this->idleTimeout);
|
||||
if ($this->workingDirectory) {
|
||||
$this->process->setWorkingDirectory($this->workingDirectory);
|
||||
}
|
||||
if ($this->input) {
|
||||
$this->process->setInput($this->input);
|
||||
}
|
||||
|
||||
if ($this->interactive && $this->isPrinted) {
|
||||
$this->process->setTty(true);
|
||||
}
|
||||
|
||||
if (isset($this->env)) {
|
||||
$this->process->setEnv($this->env);
|
||||
}
|
||||
|
||||
if (!$this->background && !$this->isPrinted) {
|
||||
$this->startTimer();
|
||||
$this->process->run();
|
||||
$this->stopTimer();
|
||||
$output = rtrim($this->process->getOutput());
|
||||
return new ResultData(
|
||||
$this->process->getExitCode(),
|
||||
$output,
|
||||
$this->getResultData()
|
||||
);
|
||||
}
|
||||
|
||||
if (!$this->background && $this->isPrinted) {
|
||||
$this->startTimer();
|
||||
$this->process->run($output_callback);
|
||||
$this->stopTimer();
|
||||
return new ResultData(
|
||||
$this->process->getExitCode(),
|
||||
$this->process->getOutput(),
|
||||
$this->getResultData()
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
$this->process->start();
|
||||
} catch (\Exception $e) {
|
||||
return new ResultData(
|
||||
$this->process->getExitCode(),
|
||||
$e->getMessage(),
|
||||
$this->getResultData()
|
||||
);
|
||||
}
|
||||
return new ResultData($this->process->getExitCode());
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
protected function stop()
|
||||
{
|
||||
if ($this->background && isset($this->process) && $this->process->isRunning()) {
|
||||
$this->process->stop();
|
||||
$this->printTaskInfo(
|
||||
"Stopped {command}",
|
||||
['command' => $this->getCommandDescription()]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $context
|
||||
*/
|
||||
protected function printAction($context = [])
|
||||
{
|
||||
$command = $this->getCommandDescription();
|
||||
$formatted_command = $this->formatCommandDisplay($command);
|
||||
|
||||
$dir = $this->workingDirectory ? " in {dir}" : "";
|
||||
$this->printTaskInfo("Running {command}$dir", [
|
||||
'command' => $formatted_command,
|
||||
'dir' => $this->workingDirectory
|
||||
] + $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $command
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
protected function formatCommandDisplay($command)
|
||||
{
|
||||
$formatted_command = str_replace("&&", "&&\n", $command);
|
||||
$formatted_command = str_replace("||", "||\n", $formatted_command);
|
||||
|
||||
return $formatted_command;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the data array to be passed to Result().
|
||||
*
|
||||
* @return array
|
||||
* The data array passed to Result().
|
||||
*/
|
||||
protected function getResultData()
|
||||
{
|
||||
if ($this->isMetadataPrinted) {
|
||||
return ['time' => $this->getExecutionTime()];
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
||||
171
core/lib/composer/vendor/consolidation/robo/scenarios/symfony2/src/Common/IO.php
vendored
Normal file
171
core/lib/composer/vendor/consolidation/robo/scenarios/symfony2/src/Common/IO.php
vendored
Normal file
@@ -0,0 +1,171 @@
|
||||
<?php
|
||||
namespace Robo\Common;
|
||||
|
||||
use Symfony\Component\Console\Helper\QuestionHelper;
|
||||
use Symfony\Component\Console\Question\ConfirmationQuestion;
|
||||
use Symfony\Component\Console\Question\Question;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
|
||||
trait IO
|
||||
{
|
||||
use InputAwareTrait;
|
||||
use OutputAwareTrait;
|
||||
|
||||
/**
|
||||
* @var \Symfony\Component\Console\Style\SymfonyStyle
|
||||
*/
|
||||
protected $io;
|
||||
|
||||
/**
|
||||
* Provide access to SymfonyStyle object.
|
||||
*
|
||||
* @return SymfonyStyle
|
||||
*
|
||||
* @see http://symfony.com/blog/new-in-symfony-2-8-console-style-guide
|
||||
*/
|
||||
protected function io()
|
||||
{
|
||||
if (!$this->io) {
|
||||
$this->io = new SymfonyStyle($this->input(), $this->output());
|
||||
}
|
||||
return $this->io;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $nonDecorated
|
||||
* @param string $decorated
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function decorationCharacter($nonDecorated, $decorated)
|
||||
{
|
||||
if (!$this->output()->isDecorated() || (strncasecmp(PHP_OS, 'WIN', 3) == 0)) {
|
||||
return $nonDecorated;
|
||||
}
|
||||
return $decorated;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $text
|
||||
*/
|
||||
protected function say($text)
|
||||
{
|
||||
$char = $this->decorationCharacter('>', '➜');
|
||||
$this->writeln("$char $text");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $text
|
||||
* @param int $length
|
||||
* @param string $color
|
||||
*/
|
||||
protected function yell($text, $length = 40, $color = 'green')
|
||||
{
|
||||
$char = $this->decorationCharacter(' ', '➜');
|
||||
$format = "$char <fg=white;bg=$color;options=bold>%s</fg=white;bg=$color;options=bold>";
|
||||
$this->formattedOutput($text, $length, $format);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $text
|
||||
* @param int $length
|
||||
* @param string $format
|
||||
*/
|
||||
protected function formattedOutput($text, $length, $format)
|
||||
{
|
||||
$lines = explode("\n", trim($text, "\n"));
|
||||
$maxLineLength = array_reduce(array_map('strlen', $lines), 'max');
|
||||
$length = max($length, $maxLineLength);
|
||||
$len = $length + 2;
|
||||
$space = str_repeat(' ', $len);
|
||||
$this->writeln(sprintf($format, $space));
|
||||
foreach ($lines as $line) {
|
||||
$line = str_pad($line, $length, ' ', STR_PAD_BOTH);
|
||||
$this->writeln(sprintf($format, " $line "));
|
||||
}
|
||||
$this->writeln(sprintf($format, $space));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $question
|
||||
* @param bool $hideAnswer
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function ask($question, $hideAnswer = false)
|
||||
{
|
||||
if ($hideAnswer) {
|
||||
return $this->askHidden($question);
|
||||
}
|
||||
return $this->doAsk(new Question($this->formatQuestion($question)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $question
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function askHidden($question)
|
||||
{
|
||||
$question = new Question($this->formatQuestion($question));
|
||||
$question->setHidden(true);
|
||||
return $this->doAsk($question);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $question
|
||||
* @param string $default
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function askDefault($question, $default)
|
||||
{
|
||||
return $this->doAsk(new Question($this->formatQuestion("$question [$default]"), $default));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $question
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function confirm($question)
|
||||
{
|
||||
return $this->doAsk(new ConfirmationQuestion($this->formatQuestion($question . ' (y/n)'), false));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Symfony\Component\Console\Question\Question $question
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function doAsk(Question $question)
|
||||
{
|
||||
return $this->getDialog()->ask($this->input(), $this->output(), $question);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $message
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function formatQuestion($message)
|
||||
{
|
||||
return "<question>? $message</question> ";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Symfony\Component\Console\Helper\QuestionHelper
|
||||
*/
|
||||
protected function getDialog()
|
||||
{
|
||||
return new QuestionHelper();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $text
|
||||
*/
|
||||
protected function writeln($text)
|
||||
{
|
||||
$this->output()->writeln($text);
|
||||
}
|
||||
}
|
||||
21
core/lib/composer/vendor/consolidation/robo/scenarios/symfony2/src/Common/InflectionTrait.php
vendored
Normal file
21
core/lib/composer/vendor/consolidation/robo/scenarios/symfony2/src/Common/InflectionTrait.php
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
namespace Robo\Common;
|
||||
|
||||
use Robo\Contract\InflectionInterface;
|
||||
|
||||
trait InflectionTrait
|
||||
{
|
||||
/**
|
||||
* Ask the provided parent class to inject all of the dependencies
|
||||
* that it has and we need.
|
||||
*
|
||||
* @param \Robo\Contract\InflectionInterface $parent
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function inflect(InflectionInterface $parent)
|
||||
{
|
||||
$parent->injectDependencies($this);
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
51
core/lib/composer/vendor/consolidation/robo/scenarios/symfony2/src/Common/InputAwareTrait.php
vendored
Normal file
51
core/lib/composer/vendor/consolidation/robo/scenarios/symfony2/src/Common/InputAwareTrait.php
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace Robo\Common;
|
||||
|
||||
use Symfony\Component\Console\Input\ArgvInput;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
|
||||
trait InputAwareTrait
|
||||
{
|
||||
/**
|
||||
* @var \Symfony\Component\Console\Input\InputInterface
|
||||
*/
|
||||
protected $input;
|
||||
|
||||
/**
|
||||
* @param \Symfony\Component\Console\Input\InputInterface $input
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @see \Symfony\Component\Console\Input\InputAwareInterface::setInput()
|
||||
*/
|
||||
public function setInput(InputInterface $input)
|
||||
{
|
||||
$this->input = $input;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Symfony\Component\Console\Input\InputInterface
|
||||
*/
|
||||
protected function input()
|
||||
{
|
||||
if (!isset($this->input)) {
|
||||
$this->setInput(new ArgvInput());
|
||||
}
|
||||
return $this->input;
|
||||
}
|
||||
|
||||
/**
|
||||
* Backwards compatibility.
|
||||
*
|
||||
* @return \Symfony\Component\Console\Input\InputInterface
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
protected function getInput()
|
||||
{
|
||||
return $this->input();
|
||||
}
|
||||
}
|
||||
38
core/lib/composer/vendor/consolidation/robo/scenarios/symfony2/src/Common/OutputAdapter.php
vendored
Normal file
38
core/lib/composer/vendor/consolidation/robo/scenarios/symfony2/src/Common/OutputAdapter.php
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
namespace Robo\Common;
|
||||
|
||||
use Robo\Contract\OutputAdapterInterface;
|
||||
use Robo\Contract\OutputAwareInterface;
|
||||
use Robo\Contract\VerbosityThresholdInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
* Adapt OutputInterface or other output function to the VerbosityThresholdInterface.
|
||||
*/
|
||||
class OutputAdapter implements OutputAdapterInterface, OutputAwareInterface
|
||||
{
|
||||
use OutputAwareTrait;
|
||||
|
||||
protected $verbosityMap = [
|
||||
VerbosityThresholdInterface::VERBOSITY_NORMAL => OutputInterface::VERBOSITY_NORMAL,
|
||||
VerbosityThresholdInterface::VERBOSITY_VERBOSE => OutputInterface::VERBOSITY_VERBOSE,
|
||||
VerbosityThresholdInterface::VERBOSITY_VERY_VERBOSE => OutputInterface::VERBOSITY_VERY_VERBOSE,
|
||||
VerbosityThresholdInterface::VERBOSITY_DEBUG => OutputInterface::VERBOSITY_DEBUG,
|
||||
];
|
||||
|
||||
public function verbosityMeetsThreshold($verbosityThreshold)
|
||||
{
|
||||
if (!isset($this->verbosityMap[$verbosityThreshold])) {
|
||||
return true;
|
||||
}
|
||||
$verbosityThreshold = $this->verbosityMap[$verbosityThreshold];
|
||||
$verbosity = $this->output()->getVerbosity();
|
||||
|
||||
return $verbosity >= $verbosityThreshold;
|
||||
}
|
||||
|
||||
public function writeMessage($message)
|
||||
{
|
||||
$this->output()->write($message);
|
||||
}
|
||||
}
|
||||
51
core/lib/composer/vendor/consolidation/robo/scenarios/symfony2/src/Common/OutputAwareTrait.php
vendored
Normal file
51
core/lib/composer/vendor/consolidation/robo/scenarios/symfony2/src/Common/OutputAwareTrait.php
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace Robo\Common;
|
||||
|
||||
use Symfony\Component\Console\Output\NullOutput;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
trait OutputAwareTrait
|
||||
{
|
||||
/**
|
||||
* @var \Symfony\Component\Console\Output\OutputInterface
|
||||
*/
|
||||
protected $output;
|
||||
|
||||
/**
|
||||
* @param \Symfony\Component\Console\Output\OutputInterface $output
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @see \Robo\Contract\OutputAwareInterface::setOutput()
|
||||
*/
|
||||
public function setOutput(OutputInterface $output)
|
||||
{
|
||||
$this->output = $output;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Symfony\Component\Console\Output\OutputInterface
|
||||
*/
|
||||
protected function output()
|
||||
{
|
||||
if (!isset($this->output)) {
|
||||
$this->setOutput(new NullOutput());
|
||||
}
|
||||
return $this->output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Backwards compatibility
|
||||
*
|
||||
* @return \Symfony\Component\Console\Output\OutputInterface
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
protected function getOutput()
|
||||
{
|
||||
return $this->output();
|
||||
}
|
||||
}
|
||||
51
core/lib/composer/vendor/consolidation/robo/scenarios/symfony2/src/Common/ProcessExecutor.php
vendored
Normal file
51
core/lib/composer/vendor/consolidation/robo/scenarios/symfony2/src/Common/ProcessExecutor.php
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace Robo\Common;
|
||||
|
||||
use Psr\Log\LoggerAwareInterface;
|
||||
use Robo\Contract\ConfigAwareInterface;
|
||||
use Robo\Contract\OutputAwareInterface;
|
||||
use Robo\Contract\VerbosityThresholdInterface;
|
||||
use Symfony\Component\Process\Process;
|
||||
|
||||
class ProcessExecutor implements ConfigAwareInterface, LoggerAwareInterface, OutputAwareInterface, VerbosityThresholdInterface
|
||||
{
|
||||
use ExecTrait;
|
||||
use TaskIO; // uses LoggerAwareTrait and ConfigAwareTrait
|
||||
use ProgressIndicatorAwareTrait;
|
||||
use OutputAwareTrait;
|
||||
|
||||
/**
|
||||
* @param Process $process
|
||||
* @return type
|
||||
*/
|
||||
public function __construct(Process $process)
|
||||
{
|
||||
$this->process = $process;
|
||||
}
|
||||
|
||||
public static function create($container, $process)
|
||||
{
|
||||
$processExecutor = new self($process);
|
||||
|
||||
$processExecutor->setLogger($container->get('logger'));
|
||||
$processExecutor->setProgressIndicator($container->get('progressIndicator'));
|
||||
$processExecutor->setConfig($container->get('config'));
|
||||
$processExecutor->setOutputAdapter($container->get('outputAdapter'));
|
||||
|
||||
return $processExecutor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
protected function getCommandDescription()
|
||||
{
|
||||
return $this->process->getCommandLine();
|
||||
}
|
||||
|
||||
public function run()
|
||||
{
|
||||
return $this->execute($this->process);
|
||||
}
|
||||
}
|
||||
79
core/lib/composer/vendor/consolidation/robo/scenarios/symfony2/src/Common/ProcessUtils.php
vendored
Normal file
79
core/lib/composer/vendor/consolidation/robo/scenarios/symfony2/src/Common/ProcessUtils.php
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is derived from part of the Symfony package, which is
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
|
||||
namespace Robo\Common;
|
||||
|
||||
use Symfony\Component\Process\Exception\InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* ProcessUtils is a bunch of utility methods. We want to allow Robo 1.x
|
||||
* to work with Symfony 4.x while remaining backwards compatibility. This
|
||||
* requires us to replace some deprecated functionality removed in Symfony.
|
||||
*/
|
||||
class ProcessUtils
|
||||
{
|
||||
/**
|
||||
* This class should not be instantiated.
|
||||
*/
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Escapes a string to be used as a shell argument.
|
||||
*
|
||||
* @param string $argument The argument that will be escaped
|
||||
*
|
||||
* @return string The escaped argument
|
||||
*
|
||||
* @deprecated since version 3.3, to be removed in 4.0. Use a command line array or give env vars to the `Process::start/run()` method instead.
|
||||
*/
|
||||
public static function escapeArgument($argument)
|
||||
{
|
||||
@trigger_error('The '.__METHOD__.'() method is a copy of a method that was deprecated by Symfony 3.3 and removed in Symfony 4; it will be removed in Robo 2.0.', E_USER_DEPRECATED);
|
||||
|
||||
//Fix for PHP bug #43784 escapeshellarg removes % from given string
|
||||
//Fix for PHP bug #49446 escapeshellarg doesn't work on Windows
|
||||
//@see https://bugs.php.net/bug.php?id=43784
|
||||
//@see https://bugs.php.net/bug.php?id=49446
|
||||
if ('\\' === DIRECTORY_SEPARATOR) {
|
||||
if ('' === $argument) {
|
||||
return escapeshellarg($argument);
|
||||
}
|
||||
|
||||
$escapedArgument = '';
|
||||
$quote = false;
|
||||
foreach (preg_split('/(")/', $argument, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE) as $part) {
|
||||
if ('"' === $part) {
|
||||
$escapedArgument .= '\\"';
|
||||
} elseif (self::isSurroundedBy($part, '%')) {
|
||||
// Avoid environment variable expansion
|
||||
$escapedArgument .= '^%"'.substr($part, 1, -1).'"^%';
|
||||
} else {
|
||||
// escape trailing backslash
|
||||
if ('\\' === substr($part, -1)) {
|
||||
$part .= '\\';
|
||||
}
|
||||
$quote = true;
|
||||
$escapedArgument .= $part;
|
||||
}
|
||||
}
|
||||
if ($quote) {
|
||||
$escapedArgument = '"'.$escapedArgument.'"';
|
||||
}
|
||||
|
||||
return $escapedArgument;
|
||||
}
|
||||
|
||||
return "'".str_replace("'", "'\\''", $argument)."'";
|
||||
}
|
||||
|
||||
private static function isSurroundedBy($arg, $char)
|
||||
{
|
||||
return 2 < strlen($arg) && $char === $arg[0] && $char === $arg[strlen($arg) - 1];
|
||||
}
|
||||
}
|
||||
201
core/lib/composer/vendor/consolidation/robo/scenarios/symfony2/src/Common/ProgressIndicator.php
vendored
Normal file
201
core/lib/composer/vendor/consolidation/robo/scenarios/symfony2/src/Common/ProgressIndicator.php
vendored
Normal file
@@ -0,0 +1,201 @@
|
||||
<?php
|
||||
namespace Robo\Common;
|
||||
|
||||
/**
|
||||
* Wrapper around \Symfony\Component\Console\Helper\ProgressBar
|
||||
*/
|
||||
class ProgressIndicator
|
||||
{
|
||||
use Timer;
|
||||
|
||||
/**
|
||||
* @var \Symfony\Component\Console\Helper\ProgressBar
|
||||
*/
|
||||
protected $progressBar;
|
||||
|
||||
/**
|
||||
* @var \Symfony\Component\Console\Output\OutputInterface
|
||||
*/
|
||||
protected $output;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $progressIndicatorRunning = false;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $autoDisplayInterval = 0;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $cachedSteps = 0;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $totalSteps = 0;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $progressBarDisplayed = false;
|
||||
|
||||
/**
|
||||
* @var \Robo\Contract\TaskInterface
|
||||
*/
|
||||
protected $owner;
|
||||
|
||||
/**
|
||||
* @param \Symfony\Component\Console\Helper\ProgressBar $progressBar
|
||||
* @param \Symfony\Component\Console\Output\OutputInterface $output
|
||||
*/
|
||||
public function __construct($progressBar, \Symfony\Component\Console\Output\OutputInterface $output)
|
||||
{
|
||||
$this->progressBar = $progressBar;
|
||||
$this->output = $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $interval
|
||||
*/
|
||||
public function setProgressBarAutoDisplayInterval($interval)
|
||||
{
|
||||
if ($this->progressIndicatorRunning) {
|
||||
return;
|
||||
}
|
||||
$this->autoDisplayInterval = $interval;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function hideProgressIndicator()
|
||||
{
|
||||
$result = $this->progressBarDisplayed;
|
||||
if ($this->progressIndicatorRunning && $this->progressBarDisplayed) {
|
||||
$this->progressBar->clear();
|
||||
// Hack: progress indicator does not reset cursor to beginning of line on 'clear'
|
||||
$this->output->write("\x0D");
|
||||
$this->progressBarDisplayed = false;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function showProgressIndicator()
|
||||
{
|
||||
if ($this->progressIndicatorRunning && !$this->progressBarDisplayed && isset($this->progressBar)) {
|
||||
$this->progressBar->display();
|
||||
$this->progressBarDisplayed = true;
|
||||
$this->advanceProgressIndicatorCachedSteps();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $visible
|
||||
*/
|
||||
public function restoreProgressIndicator($visible)
|
||||
{
|
||||
if ($visible) {
|
||||
$this->showProgressIndicator();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $totalSteps
|
||||
* @param \Robo\Contract\TaskInterface $owner
|
||||
*/
|
||||
public function startProgressIndicator($totalSteps, $owner)
|
||||
{
|
||||
if (!isset($this->progressBar)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->progressIndicatorRunning = true;
|
||||
if (!isset($this->owner)) {
|
||||
$this->owner = $owner;
|
||||
$this->startTimer();
|
||||
$this->totalSteps = $totalSteps;
|
||||
$this->autoShowProgressIndicator();
|
||||
}
|
||||
}
|
||||
|
||||
public function autoShowProgressIndicator()
|
||||
{
|
||||
if (($this->autoDisplayInterval < 0) || !isset($this->progressBar) || !$this->output->isDecorated()) {
|
||||
return;
|
||||
}
|
||||
if ($this->autoDisplayInterval <= $this->getExecutionTime()) {
|
||||
$this->autoDisplayInterval = -1;
|
||||
$this->progressBar->start($this->totalSteps);
|
||||
$this->showProgressIndicator();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function inProgress()
|
||||
{
|
||||
return $this->progressIndicatorRunning;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Robo\Contract\TaskInterface $owner
|
||||
*/
|
||||
public function stopProgressIndicator($owner)
|
||||
{
|
||||
if ($this->progressIndicatorRunning && ($this->owner === $owner)) {
|
||||
$this->cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
protected function cleanup()
|
||||
{
|
||||
$this->progressIndicatorRunning = false;
|
||||
$this->owner = null;
|
||||
if ($this->progressBarDisplayed) {
|
||||
$this->progressBar->finish();
|
||||
// Hack: progress indicator does not always finish cleanly
|
||||
$this->output->writeln('');
|
||||
$this->progressBarDisplayed = false;
|
||||
}
|
||||
$this->stopTimer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Erase progress indicator and ensure it never returns. Used
|
||||
* only during error handlers.
|
||||
*/
|
||||
public function disableProgressIndicator()
|
||||
{
|
||||
$this->cleanup();
|
||||
// ProgressIndicator is shared, so this permanently removes
|
||||
// the program's ability to display progress bars.
|
||||
$this->progressBar = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $steps
|
||||
*/
|
||||
public function advanceProgressIndicator($steps = 1)
|
||||
{
|
||||
$this->cachedSteps += $steps;
|
||||
if ($this->progressIndicatorRunning) {
|
||||
$this->autoShowProgressIndicator();
|
||||
// We only want to call `advance` if the progress bar is visible,
|
||||
// because it always displays itself when it is advanced.
|
||||
if ($this->progressBarDisplayed) {
|
||||
return $this->advanceProgressIndicatorCachedSteps();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function advanceProgressIndicatorCachedSteps()
|
||||
{
|
||||
$this->progressBar->advance($this->cachedSteps);
|
||||
$this->cachedSteps = 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
<?php
|
||||
namespace Robo\Common;
|
||||
|
||||
use Robo\Contract\ProgressIndicatorAwareInterface;
|
||||
use Robo\Contract\VerbosityThresholdInterface;
|
||||
|
||||
trait ProgressIndicatorAwareTrait
|
||||
{
|
||||
use Timer;
|
||||
|
||||
/**
|
||||
* @var null|\Robo\Common\ProgressIndicator
|
||||
*/
|
||||
protected $progressIndicator;
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function progressIndicatorSteps()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param null|\Robo\Common\ProgressIndicator $progressIndicator
|
||||
*
|
||||
* @return ProgressIndicatorAwareInterface
|
||||
*/
|
||||
public function setProgressIndicator($progressIndicator)
|
||||
{
|
||||
$this->progressIndicator = $progressIndicator;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null|bool
|
||||
*/
|
||||
protected function hideProgressIndicator()
|
||||
{
|
||||
if (!$this->progressIndicator) {
|
||||
return;
|
||||
}
|
||||
return $this->progressIndicator->hideProgressIndicator();
|
||||
}
|
||||
|
||||
protected function showProgressIndicator()
|
||||
{
|
||||
if (!$this->progressIndicator) {
|
||||
return;
|
||||
}
|
||||
$this->progressIndicator->showProgressIndicator();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $visible
|
||||
*/
|
||||
protected function restoreProgressIndicator($visible)
|
||||
{
|
||||
if (!$this->progressIndicator) {
|
||||
return;
|
||||
}
|
||||
$this->progressIndicator->restoreProgressIndicator($visible);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
protected function getTotalExecutionTime()
|
||||
{
|
||||
if (!$this->progressIndicator) {
|
||||
return 0;
|
||||
}
|
||||
return $this->progressIndicator->getExecutionTime();
|
||||
}
|
||||
|
||||
protected function startProgressIndicator()
|
||||
{
|
||||
$this->startTimer();
|
||||
if ($this instanceof VerbosityThresholdInterface
|
||||
&& !$this->verbosityMeetsThreshold()) {
|
||||
return;
|
||||
}
|
||||
if (!$this->progressIndicator) {
|
||||
return;
|
||||
}
|
||||
$totalSteps = $this->progressIndicatorSteps();
|
||||
$this->progressIndicator->startProgressIndicator($totalSteps, $this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
protected function inProgress()
|
||||
{
|
||||
if (!$this->progressIndicator) {
|
||||
return false;
|
||||
}
|
||||
return $this->progressIndicator->inProgress();
|
||||
}
|
||||
|
||||
protected function stopProgressIndicator()
|
||||
{
|
||||
$this->stopTimer();
|
||||
if (!$this->progressIndicator) {
|
||||
return;
|
||||
}
|
||||
$this->progressIndicator->stopProgressIndicator($this);
|
||||
}
|
||||
|
||||
protected function disableProgressIndicator()
|
||||
{
|
||||
$this->stopTimer();
|
||||
if (!$this->progressIndicator) {
|
||||
return;
|
||||
}
|
||||
$this->progressIndicator->disableProgressIndicator();
|
||||
}
|
||||
|
||||
protected function detatchProgressIndicator()
|
||||
{
|
||||
$this->setProgressIndicator(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $steps
|
||||
*/
|
||||
protected function advanceProgressIndicator($steps = 1)
|
||||
{
|
||||
if (!$this->progressIndicator) {
|
||||
return;
|
||||
}
|
||||
$this->progressIndicator->advanceProgressIndicator($steps);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
<?php
|
||||
namespace Robo\Common;
|
||||
|
||||
trait ResourceExistenceChecker
|
||||
{
|
||||
/**
|
||||
* Checks if the given input is a file or folder.
|
||||
*
|
||||
* @param string|string[] $resources
|
||||
* @param string $type "file", "dir", "fileAndDir"
|
||||
*
|
||||
* @return bool True if no errors were encountered otherwise false.
|
||||
*/
|
||||
protected function checkResources($resources, $type = 'fileAndDir')
|
||||
{
|
||||
if (!in_array($type, ['file', 'dir', 'fileAndDir'])) {
|
||||
throw new \InvalidArgumentException(sprintf('Invalid resource check of type "%s" used!', $type));
|
||||
}
|
||||
if (is_string($resources)) {
|
||||
$resources = [$resources];
|
||||
}
|
||||
$success = true;
|
||||
foreach ($resources as $resource) {
|
||||
$glob = glob($resource);
|
||||
if ($glob === false) {
|
||||
$this->printTaskError(sprintf('Invalid glob "%s"!', $resource), $this);
|
||||
$success = false;
|
||||
continue;
|
||||
}
|
||||
foreach ($glob as $resource) {
|
||||
if (!$this->checkResource($resource, $type)) {
|
||||
$success = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks a single resource, file or directory.
|
||||
*
|
||||
* It will print an error as well on the console.
|
||||
*
|
||||
* @param string $resource File or folder.
|
||||
* @param string $type "file", "dir", "fileAndDir"
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function checkResource($resource, $type)
|
||||
{
|
||||
switch ($type) {
|
||||
case 'file':
|
||||
if (!$this->isFile($resource)) {
|
||||
$this->printTaskError(sprintf('File "%s" does not exist!', $resource), $this);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
case 'dir':
|
||||
if (!$this->isDir($resource)) {
|
||||
$this->printTaskError(sprintf('Directory "%s" does not exist!', $resource), $this);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
case 'fileAndDir':
|
||||
if (!$this->isDir($resource) && !$this->isFile($resource)) {
|
||||
$this->printTaskError(sprintf('File or directory "%s" does not exist!', $resource), $this);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to check the often uses "source => target" file / folder arrays.
|
||||
*
|
||||
* @param string|array $resources
|
||||
*/
|
||||
protected function checkSourceAndTargetResource($resources)
|
||||
{
|
||||
if (is_string($resources)) {
|
||||
$resources = [$resources];
|
||||
}
|
||||
$sources = [];
|
||||
$targets = [];
|
||||
foreach ($resources as $source => $target) {
|
||||
$sources[] = $source;
|
||||
$target[] = $target;
|
||||
}
|
||||
$this->checkResources($sources);
|
||||
$this->checkResources($targets);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper method around phps is_dir()
|
||||
*
|
||||
* @param string $directory
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function isDir($directory)
|
||||
{
|
||||
return is_dir($directory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper method around phps file_exists()
|
||||
*
|
||||
* @param string $file
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function isFile($file)
|
||||
{
|
||||
return file_exists($file);
|
||||
}
|
||||
}
|
||||
237
core/lib/composer/vendor/consolidation/robo/scenarios/symfony2/src/Common/TaskIO.php
vendored
Normal file
237
core/lib/composer/vendor/consolidation/robo/scenarios/symfony2/src/Common/TaskIO.php
vendored
Normal file
@@ -0,0 +1,237 @@
|
||||
<?php
|
||||
namespace Robo\Common;
|
||||
|
||||
use Robo\Robo;
|
||||
use Robo\TaskInfo;
|
||||
use Consolidation\Log\ConsoleLogLevel;
|
||||
use Psr\Log\LoggerAwareTrait;
|
||||
use Psr\Log\LogLevel;
|
||||
use Robo\Contract\ProgressIndicatorAwareInterface;
|
||||
|
||||
/**
|
||||
* Task input/output methods. TaskIO is 'used' in BaseTask, so any
|
||||
* task that extends this class has access to all of the methods here.
|
||||
* printTaskInfo, printTaskSuccess, and printTaskError are the three
|
||||
* primary output methods that tasks are encouraged to use. Tasks should
|
||||
* avoid using the IO trait output methods.
|
||||
*/
|
||||
trait TaskIO
|
||||
{
|
||||
use LoggerAwareTrait;
|
||||
use ConfigAwareTrait;
|
||||
use VerbosityThresholdTrait;
|
||||
|
||||
/**
|
||||
* @return mixed|null|\Psr\Log\LoggerInterface
|
||||
*/
|
||||
public function logger()
|
||||
{
|
||||
// $this->logger should always be set in Robo core tasks.
|
||||
if ($this->logger) {
|
||||
return $this->logger;
|
||||
}
|
||||
|
||||
// TODO: Remove call to Robo::logger() once maintaining backwards
|
||||
// compatibility with legacy external Robo tasks is no longer desired.
|
||||
if (!Robo::logger()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
static $gaveDeprecationWarning = false;
|
||||
if (!$gaveDeprecationWarning) {
|
||||
trigger_error('No logger set for ' . get_class($this) . '. Use $this->task(Foo::class) rather than new Foo() in loadTasks to ensure the builder can initialize task the task, or use $this->collectionBuilder()->taskFoo() if creating one task from within another.', E_USER_DEPRECATED);
|
||||
$gaveDeprecationWarning = true;
|
||||
}
|
||||
return Robo::logger();
|
||||
}
|
||||
|
||||
/**
|
||||
* Print information about a task in progress.
|
||||
*
|
||||
* With the Symfony Console logger, NOTICE is displayed at VERBOSITY_VERBOSE
|
||||
* and INFO is displayed at VERBOSITY_VERY_VERBOSE.
|
||||
*
|
||||
* Robo overrides the default such that NOTICE is displayed at
|
||||
* VERBOSITY_NORMAL and INFO is displayed at VERBOSITY_VERBOSE.
|
||||
*
|
||||
* n.b. We should probably have printTaskNotice for our ordinary
|
||||
* output, and use printTaskInfo for less interesting messages.
|
||||
*
|
||||
* @param string $text
|
||||
* @param null|array $context
|
||||
*/
|
||||
protected function printTaskInfo($text, $context = null)
|
||||
{
|
||||
// The 'note' style is used for both 'notice' and 'info' log levels;
|
||||
// However, 'notice' is printed at VERBOSITY_NORMAL, whereas 'info'
|
||||
// is only printed at VERBOSITY_VERBOSE.
|
||||
$this->printTaskOutput(LogLevel::NOTICE, $text, $this->getTaskContext($context));
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide notification that some part of the task succeeded.
|
||||
*
|
||||
* With the Symfony Console logger, success messages are remapped to NOTICE,
|
||||
* and displayed in VERBOSITY_VERBOSE. When used with the Robo logger,
|
||||
* success messages are displayed at VERBOSITY_NORMAL.
|
||||
*
|
||||
* @param string $text
|
||||
* @param null|array $context
|
||||
*/
|
||||
protected function printTaskSuccess($text, $context = null)
|
||||
{
|
||||
// Not all loggers will recognize ConsoleLogLevel::SUCCESS.
|
||||
// We therefore log as LogLevel::NOTICE, and apply a '_level'
|
||||
// override in the context so that this message will be
|
||||
// logged as SUCCESS if that log level is recognized.
|
||||
$context['_level'] = ConsoleLogLevel::SUCCESS;
|
||||
$this->printTaskOutput(LogLevel::NOTICE, $text, $this->getTaskContext($context));
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide notification that there is something wrong, but
|
||||
* execution can continue.
|
||||
*
|
||||
* Warning messages are displayed at VERBOSITY_NORMAL.
|
||||
*
|
||||
* @param string $text
|
||||
* @param null|array $context
|
||||
*/
|
||||
protected function printTaskWarning($text, $context = null)
|
||||
{
|
||||
$this->printTaskOutput(LogLevel::WARNING, $text, $this->getTaskContext($context));
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide notification that some operation in the task failed,
|
||||
* and the task cannot continue.
|
||||
*
|
||||
* Error messages are displayed at VERBOSITY_NORMAL.
|
||||
*
|
||||
* @param string $text
|
||||
* @param null|array $context
|
||||
*/
|
||||
protected function printTaskError($text, $context = null)
|
||||
{
|
||||
$this->printTaskOutput(LogLevel::ERROR, $text, $this->getTaskContext($context));
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide debugging notification. These messages are only
|
||||
* displayed if the log level is VERBOSITY_DEBUG.
|
||||
*
|
||||
* @param string$text
|
||||
* @param null|array $context
|
||||
*/
|
||||
protected function printTaskDebug($text, $context = null)
|
||||
{
|
||||
$this->printTaskOutput(LogLevel::DEBUG, $text, $this->getTaskContext($context));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $level
|
||||
* One of the \Psr\Log\LogLevel constant
|
||||
* @param string $text
|
||||
* @param null|array $context
|
||||
*/
|
||||
protected function printTaskOutput($level, $text, $context)
|
||||
{
|
||||
if (!$this->verbosityMeetsThreshold()) {
|
||||
return;
|
||||
}
|
||||
$logger = $this->logger();
|
||||
if (!$logger) {
|
||||
return;
|
||||
}
|
||||
// Hide the progress indicator, if it is visible.
|
||||
$inProgress = $this->hideTaskProgress();
|
||||
$logger->log($level, $text, $this->getTaskContext($context));
|
||||
// After we have printed our log message, redraw the progress indicator.
|
||||
$this->showTaskProgress($inProgress);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
protected function hideTaskProgress()
|
||||
{
|
||||
$inProgress = false;
|
||||
if ($this instanceof ProgressIndicatorAwareInterface) {
|
||||
$inProgress = $this->inProgress();
|
||||
}
|
||||
|
||||
// If a progress indicator is running on this task, then we mush
|
||||
// hide it before we print anything, or its display will be overwritten.
|
||||
if ($inProgress) {
|
||||
$inProgress = $this->hideProgressIndicator();
|
||||
}
|
||||
return $inProgress;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $inProgress
|
||||
*/
|
||||
protected function showTaskProgress($inProgress)
|
||||
{
|
||||
if ($inProgress) {
|
||||
$this->restoreProgressIndicator($inProgress);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a quantity of bytes.
|
||||
*
|
||||
* @param int $size
|
||||
* @param int $precision
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function formatBytes($size, $precision = 2)
|
||||
{
|
||||
if ($size === 0) {
|
||||
return 0;
|
||||
}
|
||||
$base = log($size, 1024);
|
||||
$suffixes = array('', 'k', 'M', 'G', 'T');
|
||||
return round(pow(1024, $base - floor($base)), $precision) . $suffixes[floor($base)];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the formatted task name for use in task output.
|
||||
* This is placed in the task context under 'name', and
|
||||
* used as the log label by Robo\Common\RoboLogStyle,
|
||||
* which is inserted at the head of log messages by
|
||||
* Robo\Common\CustomLogStyle::formatMessage().
|
||||
*
|
||||
* @param null|object $task
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getPrintedTaskName($task = null)
|
||||
{
|
||||
if (!$task) {
|
||||
$task = $this;
|
||||
}
|
||||
return TaskInfo::formatTaskName($task);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param null|array $context
|
||||
*
|
||||
* @return array with context information
|
||||
*/
|
||||
protected function getTaskContext($context = null)
|
||||
{
|
||||
if (!$context) {
|
||||
$context = [];
|
||||
}
|
||||
if (!is_array($context)) {
|
||||
$context = ['task' => $context];
|
||||
}
|
||||
if (!array_key_exists('task', $context)) {
|
||||
$context['task'] = $this;
|
||||
}
|
||||
|
||||
return $context + TaskInfo::getTaskContext($context['task']);
|
||||
}
|
||||
}
|
||||
69
core/lib/composer/vendor/consolidation/robo/scenarios/symfony2/src/Common/TimeKeeper.php
vendored
Normal file
69
core/lib/composer/vendor/consolidation/robo/scenarios/symfony2/src/Common/TimeKeeper.php
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
namespace Robo\Common;
|
||||
|
||||
class TimeKeeper
|
||||
{
|
||||
const MINUTE = 60;
|
||||
const HOUR = 3600;
|
||||
const DAY = 86400;
|
||||
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
protected $startedAt;
|
||||
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
protected $finishedAt;
|
||||
|
||||
public function start()
|
||||
{
|
||||
if ($this->startedAt) {
|
||||
return;
|
||||
}
|
||||
// Get time in seconds as a float, accurate to the microsecond.
|
||||
$this->startedAt = microtime(true);
|
||||
}
|
||||
|
||||
public function stop()
|
||||
{
|
||||
$this->finishedAt = microtime(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return float|null
|
||||
*/
|
||||
public function elapsed()
|
||||
{
|
||||
$finished = $this->finishedAt ? $this->finishedAt : microtime(true);
|
||||
if ($finished - $this->startedAt <= 0) {
|
||||
return null;
|
||||
}
|
||||
return $finished - $this->startedAt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a duration into a human-readable time
|
||||
*
|
||||
* @param float $duration Duration in seconds, with fractional component
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function formatDuration($duration)
|
||||
{
|
||||
if ($duration >= self::DAY * 2) {
|
||||
return gmdate('z \d\a\y\s H:i:s', $duration);
|
||||
}
|
||||
if ($duration > self::DAY) {
|
||||
return gmdate('\1 \d\a\y H:i:s', $duration);
|
||||
}
|
||||
if ($duration > self::HOUR) {
|
||||
return gmdate("H:i:s", $duration);
|
||||
}
|
||||
if ($duration > self::MINUTE) {
|
||||
return gmdate("i:s", $duration);
|
||||
}
|
||||
return round($duration, 3).'s';
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user