/** * Set group members based on query * * If $type is \Model\Client\Client::MEMBERSHIP_AUTOMATIC, * the DynamicMembersSql property will be set to the resulting query. For * other values, the query will be executed and $type is stored as manual * membership/exclusion on the results. * * The query arguments are passed to \Model\Client\ClientManager::getClients(). * * @param integer $type Membership type * @param string|array $filter Name or array of names of a pre-defined filter routine * @param string|array $search Search parameter(s) passed to the filter * @param string|array $operator Comparision operator * @param bool|array $invert Invert query results (return all clients NOT matching criteria) * @throws \LogicException if the query does not yield exactly 1 column (internal validation, should never fail) */ public function setMembersFromQuery($type, $filter, $search, $operator, $invert) { $id = $this['Id']; $members = $this->serviceLocator->get('Model\\Client\\ClientManager')->getClients(array('Id'), null, null, $filter, $search, $operator, $invert, false, true, $type != \Model\Client\Client::MEMBERSHIP_AUTOMATIC); if ($type == \Model\Client\Client::MEMBERSHIP_AUTOMATIC) { $numCols = count($members->getRawState(\Zend\Db\Sql\Select::COLUMNS)); foreach ($members->getRawState(\Zend\Db\Sql\Select::JOINS) as $join) { $numCols += count($join['columns']); } if ($numCols != 1) { throw new \LogicException('Expected 1 column, got ' . $numCols); } $sql = new \Zend\Db\Sql\Sql($this->serviceLocator->get('Db')); $query = $sql->buildSqlString($members); $this->serviceLocator->get('Database\\Table\\GroupInfo')->update(array('request' => $query), array('hardware_id' => $id)); $this->offsetSet('DynamicMembersSql', $query); $this->update(true); // Force cache update, effectively validating query } else { // Wait until lock can be obtained while (!$this->lock()) { sleep(1); } // Get list of existing memberships $existingMemberships = array(); $groupMemberships = $this->serviceLocator->get('Database\\Table\\GroupMemberships'); $select = $groupMemberships->getSql()->select(); $select->columns(array('hardware_id', 'static'))->where(array('group_id' => $id)); foreach ($groupMemberships->selectWith($select) as $membership) { $existingMemberships[$membership['hardware_id']] = $membership['static']; } // Insert/update membership entries $connection = $groupMemberships->getAdapter()->getDriver()->getConnection(); $connection->beginTransaction(); try { foreach ($members as $member) { $member = $member['Id']; if (isset($existingMemberships[$member])) { // Update only memberships of a different type if ($existingMemberships[$member] != $type) { $groupMemberships->update(array('static' => $type), array('group_id' => $id, 'hardware_id' => $member)); } } else { $groupMemberships->insert(array('group_id' => $id, 'hardware_id' => $member, 'static' => $type)); } } $connection->commit(); } catch (\Exception $exception) { $connection->rollBack(); $this->unlock(); throw $exception; } $this->unlock(); } }