2015-04-24 14:26:44 +02:00
< ? php
namespace Icinga\Module\Director ;
use Icinga\Data\Db\DbConnection ;
2015-08-29 01:05:23 +02:00
use Icinga\Module\Director\Objects\DirectorDeploymentLog ;
2016-02-09 20:38:16 +01:00
use Icinga\Module\Director\Objects\IcingaEndpoint ;
use Icinga\Exception\ConfigurationError ;
2015-08-28 18:02:44 +02:00
use Zend_Db_Expr ;
2015-12-18 09:05:04 +01:00
use Zend_Db_Select ;
2015-04-24 14:26:44 +02:00
class Db extends DbConnection
{
protected $modules = array ();
2015-06-08 14:37:02 +02:00
protected static $zoneCache ;
protected static $commandCache ;
2016-02-09 20:14:18 +01:00
protected $settings ;
2015-04-24 14:26:44 +02:00
protected function db ()
{
return $this -> getDbAdapter ();
}
2016-02-18 13:46:24 +01:00
public function countActivitiesSinceLastDeployedConfig ()
{
$query = 'SELECT COUNT(*) FROM director_activity_log WHERE id > ('
. ' SELECT id FROM director_activity_log WHERE checksum = ('
. ' SELECT last_activity_checksum FROM director_generated_config WHERE checksum = ('
. ' SELECT config_checksum FROM director_deployment_log ORDER by id desc limit 1'
. ' )'
. ' )'
. ')' ;
return ( int ) $this -> db () -> fetchOne ( $query );
}
2016-02-09 20:38:16 +01:00
public function getMasterZoneName ()
{
return $this -> getSetting ( 'master_zone' , 'master' );
}
public function getDefaultGlobalZoneName ()
{
return $this -> getSetting ( 'default_global_zone' , 'director-global' );
}
public function getDeploymentEndpointName ()
{
$db = $this -> db ();
$query = $db -> select () -> from (
2016-02-17 16:42:42 +01:00
array ( 'z' => 'icinga_zone' ),
2016-02-09 20:38:16 +01:00
array ( 'object_name' => 'e.object_name' )
) -> join (
2016-02-17 16:42:42 +01:00
array ( 'e' => 'icinga_endpoint' ),
'e.zone_id = z.id' ,
array ()
) -> join (
array ( 'au' => 'icinga_apiuser' ),
'e.apiuser_id = au.id' ,
array ()
2016-02-09 20:38:16 +01:00
) -> where ( 'z.object_name = ?' , $this -> getMasterZoneName ())
-> order ( 'e.object_name ASC' )
-> limit ( 1 );
$name = $db -> fetchOne ( $query );
if ( ! $name ) {
throw new ConfigurationError (
2016-02-17 16:42:42 +01:00
'Unable to detect your deployment endpoint'
2016-02-09 20:38:16 +01:00
);
}
return $name ;
}
public function getDeploymentEndpoint ()
{
return IcingaEndpoint :: load ( $this -> getDeploymentEndpointName (), $this );
}
2016-02-09 20:14:18 +01:00
public function getSetting ( $name , $default = null )
{
if ( $this -> settings === null ) {
$this -> fetchSettings ();
}
if ( array_key_exists ( $name , $this -> settings )) {
return $this -> settings [ $name ];
}
return $default ;
}
public function storeSetting ( $name , $value )
{
$db = $this -> db ();
$updated = $db -> update (
'director_setting' ,
array ( 'setting_value' => $value ),
$db -> quoteInto ( 'setting_name = ?' , $name )
);
if ( $updated === 0 ) {
$db -> insert (
'director_setting' ,
array (
'setting_name' => $name ,
'setting_value' => $value ,
)
);
}
if ( $this -> settings !== null ) {
$this -> settings [ $name ] = $value ;
}
return $this ;
}
public function fetchSettings ( $force = true )
{
if ( $force || $this -> settings === null ) {
$db = $this -> db ();
$query = $db -> select () -> from (
array ( 's' => 'director_setting' ),
array ( 'setting_name' , 'setting_value' )
);
$this -> settings = ( array ) $db -> fetchPairs ( $query );
}
return $this -> settings ;
}
2015-11-17 21:14:33 +01:00
public function getActivitylogNeighbors ( $id , $type = null , $name = null )
{
$db = $this -> db ();
$greater = $db -> select () -> from (
array ( 'g' => 'director_activity_log' ),
array ( 'id' => 'MIN(g.id)' )
) -> where ( 'id > ?' , ( int ) $id );
$smaller = $db -> select () -> from (
array ( 'l' => 'director_activity_log' ),
array ( 'id' => 'MAX(l.id)' )
) -> where ( 'id < ?' , ( int ) $id );
if ( $type !== null ) {
$greater -> where ( 'object_type = ?' , $type );
$smaller -> where ( 'object_type = ?' , $type );
}
if ( $name !== null ) {
$greater -> where ( 'object_name = ?' , $name );
$smaller -> where ( 'object_name = ?' , $name );
}
$query = $db -> select () -> from (
array ( 'gt' => $greater ),
array (
'prev' => 'lt.id' ,
'next' => 'gt.id'
)
) -> join (
array ( 'lt' => $smaller ),
null ,
array ()
);
return $db -> fetchRow ( $query );
}
2015-06-18 11:01:45 +02:00
public function fetchActivityLogEntryById ( $id )
2015-06-01 14:33:07 +02:00
{
$sql = 'SELECT * FROM director_activity_log WHERE id = ' . ( int ) $id ;
return $this -> db () -> fetchRow ( $sql );
}
2016-02-24 11:08:30 +01:00
public function fetchActivityLogChecksumById ( $id , $binary = true )
{
$sql = 'SELECT checksum FROM director_activity_log WHERE id = ' . ( int ) $id ;
$result = $this -> db () -> fetchOne ( $sql );
if ( is_resource ( $result )) {
$result = stream_get_contents ( $result );
}
if ( $binary ) {
return $result ;
} else {
return bin2hex ( $result );
}
}
2015-06-18 11:01:45 +02:00
public function fetchActivityLogEntry ( $checksum )
2015-06-23 16:45:25 +02:00
{
2015-06-23 16:12:26 +02:00
if ( $this -> getDbType () === 'pgsql' ) {
2015-08-28 18:02:44 +02:00
$checksum = new Zend_Db_Expr ( " \\ x " . bin2hex ( $checksum ));
2015-06-23 16:12:26 +02:00
}
2015-06-18 11:01:45 +02:00
$sql = 'SELECT * FROM director_activity_log WHERE checksum = ?' ;
2015-06-23 16:45:25 +02:00
$ret = $this -> db () -> fetchRow ( $sql , $checksum );
if ( is_resource ( $ret -> checksum )) {
$ret -> checksum = stream_get_contents ( $ret -> checksum );
}
if ( is_resource ( $ret -> parent_checksum )) {
$ret -> checksum = stream_get_contents ( $ret -> parent_checksum );
}
2015-06-18 11:01:45 +02:00
2015-06-23 16:45:25 +02:00
return $ret ;
2015-06-18 11:01:45 +02:00
}
2015-04-24 15:57:01 +02:00
public function getLastActivityChecksum ()
{
2015-06-23 15:24:05 +02:00
if ( $this -> getDbType () === 'pgsql' ) {
2015-06-23 13:28:14 +02:00
$select = " SELECT checksum FROM (SELECT * FROM (SELECT 1 AS pos, LOWER(ENCODE(checksum, 'hex')) AS checksum FROM director_activity_log ORDER BY change_time DESC LIMIT 1) a UNION SELECT 2 AS pos, '' AS checksum) u ORDER BY pos LIMIT 1 " ;
2015-06-23 15:24:05 +02:00
} else {
$select = " SELECT checksum FROM (SELECT * FROM (SELECT 1 AS pos, LOWER(HEX(checksum)) AS checksum FROM director_activity_log ORDER BY change_time DESC LIMIT 1) a UNION SELECT 2 AS pos, '' AS checksum) u ORDER BY pos LIMIT 1 " ;
2015-06-23 13:28:14 +02:00
}
2015-04-24 15:57:01 +02:00
return $this -> db () -> fetchOne ( $select );
}
2015-07-27 22:39:29 +02:00
public function fetchImportStatistics ()
{
$query = " SELECT 'imported_properties' AS stat_name, COUNT(*) AS stat_value "
. " FROM import_run i "
. " JOIN imported_rowset_row rs ON i.rowset_checksum = rs.rowset_checksum "
. " JOIN imported_row_property rp ON rp.row_checksum = rs.row_checksum "
. " UNION ALL "
. " SELECT 'imported_rows' AS stat_name, COUNT(*) AS stat_value "
. " FROM import_run i "
. " JOIN imported_rowset_row rs ON i.rowset_checksum = rs.rowset_checksum "
. " UNION ALL "
. " SELECT 'unique_rows' AS stat_name, COUNT(*) AS stat_value "
. " FROM imported_row "
. " UNION ALL "
. " SELECT 'unique_properties' AS stat_name, COUNT(*) AS stat_value "
. " FROM imported_property "
;
return $this -> db () -> fetchPairs ( $query );
}
2015-07-26 15:36:32 +02:00
public function getImportrunRowsetChecksum ( $id )
{
$db = $this -> db ();
$query = $db -> select ()
-> from ( 'import_run' , 'rowset_checksum' )
-> where ( 'id = ?' , $id );
return $db -> fetchOne ( $query );
}
2015-08-02 13:29:20 +02:00
protected function fetchTemplateRelations ( $type )
2015-07-29 17:19:45 +02:00
{
$db = $this -> db ();
$query = $db -> select () -> from (
2015-07-30 08:19:34 +02:00
array ( 'p' => 'icinga_' . $type ),
2015-07-29 17:19:45 +02:00
array (
2015-07-30 08:19:34 +02:00
'name' => 'o.object_name' ,
'parent' => 'p.object_name'
2015-07-29 17:19:45 +02:00
)
) -> join (
2015-07-30 08:19:34 +02:00
array ( 'i' => 'icinga_' . $type . '_inheritance' ),
'p.id = i.parent_' . $type . '_id' ,
2015-07-29 17:19:45 +02:00
array ()
) -> join (
2015-07-30 08:19:34 +02:00
array ( 'o' => 'icinga_' . $type ),
'o.id = i.' . $type . '_id' ,
2015-07-29 17:19:45 +02:00
array ()
2015-07-30 08:19:34 +02:00
) -> where ( " o.object_type = 'template' " )
-> order ( 'p.object_name' )
-> order ( 'o.object_name' );
2015-07-29 17:19:45 +02:00
2015-08-02 13:29:20 +02:00
return $db -> fetchAll ( $query );
}
public function fetchTemplateTree ( $type )
{
$relations = $this -> fetchTemplateRelations ( $type );
2015-07-29 17:19:45 +02:00
$children = array ();
2015-07-30 08:19:34 +02:00
$objects = array ();
2015-07-29 17:19:45 +02:00
foreach ( $relations as $rel ) {
2015-07-30 08:19:34 +02:00
foreach ( array ( 'name' , 'parent' ) as $col ) {
if ( ! array_key_exists ( $rel -> $col , $objects )) {
$objects [ $rel -> $col ] = ( object ) array (
2015-07-29 17:19:45 +02:00
'name' => $rel -> $col ,
'children' => array ()
);
}
}
}
2015-07-30 08:19:34 +02:00
2015-07-29 17:19:45 +02:00
foreach ( $relations as $rel ) {
2015-07-30 08:19:34 +02:00
$objects [ $rel -> parent ] -> children [ $rel -> name ] = $objects [ $rel -> name ];
$children [ $rel -> name ] = $rel -> parent ;
2015-07-29 17:19:45 +02:00
}
2015-07-30 08:19:34 +02:00
foreach ( $children as $name => $object ) {
unset ( $objects [ $name ]);
2015-07-29 17:19:45 +02:00
}
2015-07-30 08:19:34 +02:00
return $objects ;
2015-07-29 17:19:45 +02:00
}
2015-11-25 21:01:11 +01:00
public function fetchLatestImportedRows ( $source , $desiredColumns = null )
2015-07-22 23:33:24 +02:00
{
$db = $this -> db ();
2015-11-25 21:01:11 +01:00
if ( $desiredColumns === null ) {
$columns = null ;
} else {
$columns = array ();
foreach ( $desiredColumns as $column ) {
if ( false === ( $pos = strpos ( $column , '.' ))) {
$columns [ $column ] = $column ;
} else {
$column = substr ( $column , 0 , $pos );
$columns [ $column ] = $column ;
}
}
}
2015-07-22 23:33:24 +02:00
$lastRun = $db -> select () -> from ( 'import_run' , array ( 'rowset_checksum' ));
if ( is_int ( $source ) || ctype_digit ( $source )) {
$lastRun -> where ( 'source_id = ?' , $source );
} else {
$lastRun -> where ( 'source_name = ?' , $source );
}
$lastRun -> order ( 'start_time DESC' ) -> limit ( 1 );
$checksum = $db -> fetchOne ( $lastRun );
2015-11-25 21:57:12 +01:00
// TODO: Postgres decoding?
2015-07-22 23:33:24 +02:00
return $this -> fetchImportedRowsetRows ( $checksum , $columns );
}
2015-11-25 21:54:42 +01:00
public function fetchImportedRowsetRows ( $checksum , $columns )
{
$db = $this -> db ();
$query = $db -> select () -> from (
array ( 'rsr' => 'imported_rowset_row' ),
array (
'object_name' => 'r.object_name' ,
'property_name' => 'p.property_name' ,
'property_value' => 'p.property_value' ,
'format' => 'p.format'
)
) -> join (
array ( 'r' => 'imported_row' ),
'rsr.row_checksum = r.checksum' ,
array ()
) -> join (
array ( 'rp' => 'imported_row_property' ),
'r.checksum = rp.row_checksum' ,
array ()
) -> join (
array ( 'p' => 'imported_property' ),
'p.checksum = rp.property_checksum' ,
array ()
) -> where ( 'rsr.rowset_checksum = ?' , $checksum ) -> order ( 'r.object_name' );
if ( $columns === null ) {
$columns = $this -> listImportedRowsetColumnNames ( $checksum );
} else {
$query -> where ( 'p.property_name IN (?)' , $columns );
}
$result = array ();
$empty = ( object ) array ();
foreach ( $columns as $k => $v ) {
2015-12-03 15:05:51 +01:00
$empty -> $k = null ;
2015-11-25 21:54:42 +01:00
}
foreach ( $db -> fetchAll ( $query ) as $row ) {
if ( ! array_key_exists ( $row -> object_name , $result )) {
$result [ $row -> object_name ] = clone ( $empty );
}
if ( $row -> format === 'json' ) {
$result [ $row -> object_name ] -> { $row -> property_name } = json_decode ( $row -> property_value );
} else {
$result [ $row -> object_name ] -> { $row -> property_name } = $row -> property_value ;
}
}
return $result ;
}
2015-08-28 23:46:40 +02:00
public function getLatestImportedChecksum ( $source )
{
if ( $this -> getDbType () === 'pgsql' ) {
$col = " LOWER(ENCODE(rowset_checksum, 'hex')) " ;
} else {
$col = '(LOWER(HEX(import_run.rowset_checksum)))' ;
}
$db = $this -> db ();
$lastRun = $db -> select () -> from ( 'import_run' , array ( $col ));
if ( is_int ( $source ) || ctype_digit ( $source )) {
$lastRun -> where ( 'source_id = ?' , ( int ) $source );
} else {
$lastRun -> where ( 'source_name = ?' , $source );
}
$lastRun -> order ( 'start_time DESC' ) -> limit ( 1 );
return $db -> fetchOne ( $lastRun );
}
2015-12-18 09:05:04 +01:00
public function getObjectSummary ()
{
$types = array (
'host' ,
'hostgroup' ,
'service' ,
'servicegroup' ,
'user' ,
'usergroup' ,
2016-02-17 17:21:36 +01:00
'command' ,
2015-12-18 09:05:04 +01:00
'timeperiod' ,
'apiuser' ,
'endpoint' ,
'zone' ,
);
$queries = array ();
$db = $this -> db ();
foreach ( $types as $type ) {
$queries [] = $db -> select () -> from (
2016-02-02 17:42:09 +01:00
array ( 'o' => 'icinga_' . $type ),
2015-12-18 09:05:04 +01:00
array (
'icinga_type' => " (' " . $type . " ') " ,
2016-02-02 17:42:09 +01:00
'cnt_object' => " COALESCE(SUM(CASE WHEN o.object_type = 'object' THEN 1 ELSE 0 END), 0) " ,
'cnt_template' => " COALESCE(SUM(CASE WHEN o.object_type = 'template' THEN 1 ELSE 0 END), 0) " ,
'cnt_external' => " COALESCE(SUM(CASE WHEN o.object_type = 'external_object' THEN 1 ELSE 0 END), 0) " ,
2015-12-18 09:05:04 +01:00
'cnt_total' => 'COUNT(*)' ,
)
);
}
$query = $this -> db () -> select () -> union ( $queries , Zend_Db_Select :: SQL_UNION_ALL );
$result = array ();
foreach ( $db -> fetchAll ( $query ) as $row ) {
$result [ $row -> icinga_type ] = $row ;
}
return $result ;
}
2015-07-22 23:33:24 +02:00
public function listImportedRowsetColumnNames ( $checksum )
{
$db = $this -> db ();
$query = $db -> select () -> distinct () -> from (
array ( 'p' => 'imported_property' ),
'property_name'
) -> join (
array ( 'rp' => 'imported_row_property' ),
'rp.property_checksum = p.checksum' ,
array ()
) -> join (
array ( 'rsr' => 'imported_rowset_row' ),
'rsr.row_checksum = rp.row_checksum' ,
array ()
) -> where ( 'rsr.rowset_checksum = ?' , $checksum );
return $db -> fetchCol ( $query );
}
2015-06-01 16:30:24 +02:00
public function enumCommands ()
{
2015-07-29 18:07:21 +02:00
return $this -> enumIcingaObjects ( 'command' );
2015-06-01 16:30:24 +02:00
}
2015-07-29 18:07:21 +02:00
public function enumCheckcommands ()
2015-04-24 14:26:44 +02:00
{
2015-07-29 18:07:21 +02:00
$filters = array (
'methods_execute IN (?)' => array ( 'PluginCheck' , 'IcingaCheck' ),
);
return $this -> enumIcingaObjects ( 'command' , $filters );
2015-06-08 14:37:02 +02:00
}
public function getZoneName ( $id )
{
$objects = $this -> enumZones ();
return $objects [ $id ];
}
public function getCommandName ( $id )
{
$objects = $this -> enumCommands ();
return $objects [ $id ];
2015-04-24 14:26:44 +02:00
}
2015-07-29 18:07:21 +02:00
public function enumZones ()
2015-04-24 14:26:44 +02:00
{
2015-07-29 18:07:21 +02:00
return $this -> enumIcingaObjects ( 'zone' );
2015-04-24 14:26:44 +02:00
}
2015-06-02 17:29:07 +02:00
2015-12-02 21:31:38 +01:00
public function enumNonglobalZones ()
{
$filters = array ( 'is_global = ?' => 'n' );
return $this -> enumIcingaObjects ( 'zone' , $filters );
}
2015-07-29 18:07:21 +02:00
public function enumZoneTemplates ()
2015-07-28 15:19:37 +02:00
{
2015-07-29 18:07:21 +02:00
return $this -> enumIcingaTemplates ( 'zone' );
2015-07-28 15:19:37 +02:00
}
2015-07-29 18:07:21 +02:00
public function enumHosts ()
2015-07-24 09:51:31 +02:00
{
2015-07-29 18:07:21 +02:00
return $this -> enumIcingaObjects ( 'host' );
}
2015-07-24 09:51:31 +02:00
2015-07-29 18:07:21 +02:00
public function enumHostTemplates ()
{
return $this -> enumIcingaTemplates ( 'host' );
2015-07-24 09:51:31 +02:00
}
2015-06-02 17:29:07 +02:00
public function enumHostgroups ()
{
2015-07-29 18:07:21 +02:00
return $this -> enumIcingaObjects ( 'hostgroup' );
2015-06-02 17:29:07 +02:00
}
2015-06-03 14:59:29 +02:00
public function enumServices ()
{
2015-07-29 18:07:21 +02:00
return $this -> enumIcingaObjects ( 'service' );
2015-06-03 14:59:29 +02:00
}
2015-07-28 15:19:37 +02:00
public function enumServiceTemplates ()
{
2015-07-29 18:07:21 +02:00
return $this -> enumIcingaTemplates ( 'service' );
2015-07-28 15:19:37 +02:00
}
2015-06-03 14:59:29 +02:00
public function enumServicegroups ()
{
2015-07-29 18:07:21 +02:00
return $this -> enumIcingaObjects ( 'servicegroup' );
2015-06-03 14:59:29 +02:00
}
2015-06-08 14:37:02 +02:00
2015-06-12 13:16:41 +02:00
public function enumUsers ()
{
2015-07-29 18:07:21 +02:00
return $this -> enumIcingaObjects ( 'user' );
}
public function enumUserTemplates ()
{
return $this -> enumIcingaTemplates ( 'user' );
}
public function enumUsergroups ()
{
return $this -> enumIcingaObjects ( 'usergroup' );
}
2015-12-17 14:39:28 +01:00
public function enumApiUsers ()
{
return $this -> enumIcingaObjects ( 'apiuser' );
}
2015-07-29 18:07:21 +02:00
public function enumSyncRule ()
{
return $this -> enum ( 'sync_rule' , array ( 'id' , 'rule_name' ));
2015-06-12 13:16:41 +02:00
}
2015-07-24 09:51:31 +02:00
public function enumImportSource ()
{
2015-07-30 08:33:35 +02:00
return $this -> enum ( 'import_source' , array ( 'id' , 'source_name' ));
2015-07-24 09:51:31 +02:00
}
2015-07-28 11:49:30 +02:00
public function enumDatalist ()
{
2015-07-29 18:07:21 +02:00
return $this -> enum ( 'director_datalist' , array ( 'id' , 'list_name' ));
2015-07-28 11:49:30 +02:00
}
2015-07-28 15:19:37 +02:00
public function enumDatafields ()
{
2015-07-29 18:07:21 +02:00
return $this -> enum ( 'director_datafield' , array (
2015-07-28 15:19:37 +02:00
'id' ,
2015-07-29 18:07:21 +02:00
" caption || ' (' || varname || ')' " ,
));
2015-07-28 15:19:37 +02:00
}
2015-07-29 18:07:21 +02:00
public function enum ( $table , $columns = null , $filters = array ())
2015-06-12 13:16:41 +02:00
{
2015-07-29 18:07:21 +02:00
if ( $columns === null ) {
$columns = array ( 'id' , 'object_name' );
}
$select = $this -> db () -> select () -> from ( $table , $columns ) -> order ( $columns [ 1 ]);
foreach ( $filters as $key => $val ) {
$select -> where ( $key , $val );
}
2015-06-12 13:16:41 +02:00
return $this -> db () -> fetchPairs ( $select );
}
2015-07-29 18:07:21 +02:00
public function enumIcingaObjects ( $type , $filters = array ())
2015-06-08 14:37:02 +02:00
{
2015-12-02 20:34:34 +01:00
$filters = array (
'object_type IN (?)' => array ( 'object' , 'external_object' )
) + $filters ;
2015-07-29 18:07:21 +02:00
return $this -> enum ( 'icinga_' . $type , null , $filters );
2015-06-08 14:37:02 +02:00
}
2015-07-29 18:07:21 +02:00
public function enumIcingaTemplates ( $type , $filters = array ())
2015-06-08 14:37:02 +02:00
{
2015-07-29 18:07:21 +02:00
$filters = array ( 'object_type = ?' => 'template' ) + $filters ;
return $this -> enum ( 'icinga_' . $type , null , $filters );
2015-06-08 14:37:02 +02:00
}
2015-08-29 01:05:23 +02:00
2015-10-15 23:48:36 +02:00
public function fetchDistinctHostVars ()
{
$select = $this -> db () -> select () -> distinct () -> from (
array ( 'hv' => 'icinga_host_var' ),
array (
'varname' => 'hv.varname' ,
'format' => 'hv.format' ,
'caption' => 'df.caption' ,
'datatype' => 'df.datatype'
)
) -> joinLeft (
array ( 'df' => 'director_datafield' ),
'df.varname = hv.varname' ,
array ()
) -> order ( 'varname' );
return $this -> db () -> fetchAll ( $select );
}
2015-08-29 01:05:23 +02:00
public function getUncollectedDeployments ()
{
$db = $this -> db ();
$query = $db -> select ()
-> from ( 'director_deployment_log' )
-> where ( 'stage_name IS NOT NULL' )
-> where ( 'stage_collected IS NULL' )
2015-09-29 18:53:53 +02:00
-> where ( 'startup_succeeded IS NULL' )
2015-08-29 01:05:23 +02:00
-> order ( 'stage_name' );
return DirectorDeploymentLog :: loadAll ( $this , $query , 'stage_name' );
}
2015-04-24 14:26:44 +02:00
}