'o.object_name', 'object_type' => 'o.object_type', 'disabled' => 'o.disabled', 'uuid' => 'o.uuid', ]; protected $searchColumns = ['o.object_name']; protected $showColumns = ['object_name' => 'Name']; protected $filterObjectType = 'object'; protected $type; protected $baseObjectUrl; /** @var IcingaObject */ protected $dummyObject; protected $leftSubQuery; protected $rightSubQuery; /** @var Auth */ private $auth; /** * @param $type * @param Db $db * @return static */ public static function create($type, Db $db) { $class = __NAMESPACE__ . '\\ObjectsTable' . ucfirst($type); if (! class_exists($class)) { $class = __CLASS__; } /** @var static $table */ $table = new $class($db); $table->type = $type; return $table; } public function getType() { return $this->type; } /** * @param string $url * @return $this */ public function setBaseObjectUrl($url) { $this->baseObjectUrl = $url; return $this; } /** * @return Auth */ public function getAuth() { return $this->auth; } public function setAuth(Auth $auth) { $this->auth = $auth; return $this; } public function filterObjectType($type) { $this->filterObjectType = $type; return $this; } public function addObjectRestriction(ObjectRestriction $restriction) { $this->objectRestrictions[$restriction->getName()] = $restriction; return $this; } public function getColumns() { return $this->columns; } public function getColumnsToBeRendered() { return $this->showColumns; } public function filterTemplate( IcingaObject $template, $inheritance = Db\IcingaObjectFilterHelper::INHERIT_DIRECT ) { IcingaObjectFilterHelper::filterByTemplate( $this->getQuery(), $template, 'o', $inheritance ); return $this; } protected function getMainLinkLabel($row) { return $row->object_name; } protected function renderObjectNameColumn($row) { $type = $this->baseObjectUrl; $url = Url::fromPath("director/${type}", [ 'uuid' => Uuid::fromBytes($row->uuid)->toString() ]); return static::td(Link::create($this->getMainLinkLabel($row), $url)); } protected function renderExtraColumns($row) { $columns = $this->getColumnsToBeRendered(); unset($columns['object_name']); $cols = []; foreach ($columns as $key => & $label) { $cols[] = static::td($row->$key); } return $cols; } public function renderRow($row) { if (isset($row->uuid) && is_resource($row->uuid)) { $row->uuid = stream_get_contents($row->uuid); } $tr = static::tr([ $this->renderObjectNameColumn($row), $this->renderExtraColumns($row) ]); $classes = $this->getRowClasses($row); if ($row->disabled === 'y') { $classes[] = 'disabled'; } if (! empty($classes)) { $tr->getAttributes()->add('class', $classes); } return $tr; } protected function getRowClasses($row) { // TODO: remove isset, to figure out where it is missing if (isset($row->branch_uuid) && $row->branch_uuid !== null) { return ['branch_modified']; } return []; } protected function applyObjectTypeFilter(ZfSelect $query, ZfSelect $right = null) { if ($right) { $right->where( 'bo.object_type = ?', $this->filterObjectType ); } return $query->where( 'o.object_type = ?', $this->filterObjectType ); } protected function applyRestrictions(ZfSelect $query) { foreach ($this->getRestrictions() as $restriction) { $restriction->applyToQuery($query); } return $query; } protected function getRestrictions() { if ($this->objectRestrictions === null) { $this->objectRestrictions = $this->loadRestrictions(); } return $this->objectRestrictions; } protected function loadRestrictions() { /** @var Db $db */ $db = $this->connection(); $auth = $this->getAuth(); return [ new HostgroupRestriction($db, $auth), new FilterByNameRestriction($db, $auth, $this->getDummyObject()->getShortTableName()) ]; } /** * @return IcingaObject */ protected function getDummyObject() { if ($this->dummyObject === null) { $type = $this->getType(); $this->dummyObject = IcingaObject::createByType($type); } return $this->dummyObject; } protected function prepareQuery() { $table = $this->getDummyObject()->getTableName(); if ($this->branchUuid) { $this->columns['branch_uuid'] = 'bo.branch_uuid'; } $columns = $this->getColumns(); if ($this->branchUuid) { $columns = $this->branchifyColumns($columns); $this->stripSearchColumnAliases(); } $query = $this->db()->select()->from(['o' => $table], $columns); if ($this->branchUuid) { $right = clone($query); // Hint: Right part has only those with object = null // This means that restrictions on $right would hide all // new rows. Dedicated restriction logic for the branch-only // part of thw union are not required, we assume that restrictions // for new objects have been checked once they have been created $query = $this->applyRestrictions($query); /** @var Db $conn */ $conn = $this->connection(); $query->joinLeft( ['bo' => "branched_$table"], // TODO: PgHexFunc $this->db()->quoteInto( 'bo.uuid = o.uuid AND bo.branch_uuid = ?', $conn->quoteBinary($this->branchUuid->getBytes()) ), [] )->where("(bo.branch_deleted IS NULL OR bo.branch_deleted = 'n')"); $this->applyObjectTypeFilter($query, $right); $right->joinRight( ['bo' => "branched_$table"], 'bo.uuid = o.uuid', [] ) ->where('o.uuid IS NULL') ->where('bo.branch_uuid = ?', $conn->quoteBinary($this->branchUuid->getBytes())); $this->leftSubQuery = $query; $this->rightSubQuery = $right; $query = $this->db()->select()->union([ 'l' => new DbSelectParenthesis($query), 'r' => new DbSelectParenthesis($right), ]); $query = $this->db()->select()->from(['u' => $query]); $query->order('object_name')->limit(100); } else { $this->applyObjectTypeFilter($query); $query->order('o.object_name')->limit(100); } return $query; } public function removeQueryLimit() { $query = $this->getQuery(); $query->reset($query::LIMIT_OFFSET); $query->reset($query::LIMIT_COUNT); return $this; } }