%PDF- %PDF-
Direktori : /home/vacivi36/intranet.vacivitta.com.br/protected/humhub/modules/stream/actions/ |
Current File : /home/vacivi36/intranet.vacivitta.com.br/protected/humhub/modules/stream/actions/Stream.php |
<?php /** * @link https://www.humhub.org/ * @copyright Copyright (c) 2018 HumHub GmbH & Co. KG * @license https://www.humhub.com/licences */ namespace humhub\modules\stream\actions; use humhub\components\Request; use humhub\modules\stream\events\StreamResponseEvent; use humhub\modules\user\models\User; use Yii; use yii\base\Action; use yii\base\Exception; use humhub\modules\content\widgets\stream\StreamEntryWidget; use humhub\modules\content\widgets\stream\StreamEntryOptions; use humhub\modules\stream\models\StreamQuery; use humhub\modules\stream\models\WallStreamQuery; use humhub\modules\content\models\Content; /** * Stream is the basic action for content streams. * * JSON output structure: * content - array, content id is key * id - int, id of content * guid - string, guid of content * pinned - boolean, is content pinned * archived - boolean, i scontent is archived * output - string, the rendered html output of content * total - int, total of content records * isLast - boolean, is last content * contentOrder - array, list of content ids * * * @author luke * @since 0.11 */ abstract class Stream extends Action { use LegacyStreamTrait; /** * @event Event triggered before stream filter handlers are applied * This can be used for adding filters. * @since 1.7 */ const EVENT_BEFORE_APPLY_FILTERS = 'beforeApplyFilters'; /** * @event Event triggered after stream filter handlers are applied * This can be used for last modifications to the query. * @since 1.7 */ const EVENT_AFTER_APPLY_FILTERS = 'afterApplyFilters'; /** * @event Event triggered after query fetch, can be used to manipulate the * stream response. E.g. inject additional entries. * @since 1.7 */ const EVENT_AFTER_FETCH = 'afterQueryFetch'; /** * Sort by creation sort value */ const SORT_CREATED_AT = 'c'; /** * Sort by update sort value */ const SORT_UPDATED_AT = 'u'; /** * @var string * @deprecated since 1.6 use ActivityStreamAction */ const MODE_NORMAL = 'normal'; /** * @var string * @deprecated since 1.6 use ActivityStreamAction */ const MODE_ACTIVITY = 'activity'; /** * @var string * @deprecated since 1.7 use BaseStreamEntryWidget::VIEW_MODE_DASHBOARD */ const FROM_DASHBOARD = 'dashboard'; /** * Maximum wall entries per request * @deprecated since 1.7 not in use */ const MAX_LIMIT = 50; /** * Optional stream user if no user is specified, the current logged in user will be used. * * @var User */ public $user; /** * Used to load single content entries. * @since 1.2 */ public $contentId; /** * Sorting Mode * * @var int */ public $sort; /** * Maximum wall entries to return * @var int */ public $limit = 4; /** * Filters * * @var array */ public $filters = []; /** * Can be used to append or overwrite filter handlers without the need of overwriting the StreamQuery class. * @var array * @since 1.7 */ public $filterHandlers = []; /** * Used to filter the stream content entry classes against a given array. * @var array * @since 1.2 */ public $includes = []; /** * Used to filter our specific types * @var array * @since 1.2 */ public $excludes = []; /** * Stream query model instance * @var StreamQuery * @since 1.2 */ protected $streamQuery; /** * @var string suppress similar content types in a row */ public $streamQueryClass = WallStreamQuery::class; /** * @var string can be used in special streams to force a specific stream entry widget to be used when rendering */ public $streamEntryWidgetClass; /** * @var StreamEntryOptions default render option for stream entries initialized by [[initStreamEntryOptions()]] */ public $streamEntryOptions; /** * @var string can be used to set view context in request */ public $viewContext; /** * @inheritdoc * @throws \yii\base\InvalidConfigException */ public function init() { parent::init(); if(!$this->user) { $this->user = Yii::$app->user->identity; } if (!$this->isSingleContentRequest()) { $this->excludes = array_merge($this->excludes, Yii::$app->getModule('stream')->streamExcludes); } $this->streamQuery = $this->initQuery(); if (!Yii::$app->request->isConsoleRequest) { $this->streamQuery->load(Yii::$app->request->get()); if(!$this->viewContext) { $this->viewContext = Yii::$app->request->get('viewContext'); } } $this->beforeApplyFilters(); $this->streamQuery->query(true); $this->afterApplyFilters(); } /** * Initializes the StreamQuery instance. By default [[streamQueryClass]] property will be used to initialize the instance. * * Subclasses may overwrite this function in order to add or remove custom stream filters or set other default * settings of your StreamQuery instance. * * Example usage: * * ```php * protected function initQuery($options = []) * { * $query = parent::initQuery($options); * $query->addFilterHandler(new CustomStreamFilter()); * return $query; * } * ``` * * @param array $options instance attribute options * @return StreamQuery * @throws \yii\base\InvalidConfigException * @since 1.6 */ protected function initQuery($options = []) { $options['class'] = $this->streamQueryClass; $instance = Yii::createObject($options); $instance->forUser($this->user); return $instance; } /** * This function is called right before the StreamQuery is built and all filters are applied. * At this point the StreamQuery has already been loaded with request data. * Subclasses may overwrite this function in order to do some last settings on the StreamQuery instance. * * When overriding this method, make sure you call the parent implementation like the following: * * ```php * public function beforeApplyFilters() * { * // Add some filters here * * parent::beforeApplyFilters(); * } * ``` * * When overriding this method, make sure you call the parent implementation at the beginning of your function. * @throws \yii\base\InvalidConfigException */ protected function beforeApplyFilters() { $this->streamQuery->addFilterHandlers($this->filterHandlers); // Merge configured filters set for this action with request filters. $this->streamQuery->addFilter($this->filters); $this->streamQuery->includes($this->includes); $this->streamQuery->excludes($this->excludes); $this->streamQuery->forUser($this->user); // Overwrite limit if there was no setting in the request. if (empty($this->streamQuery->limit)) { $this->streamQuery->limit = $this->limit; } // Overwrite sort if there was no setting in the request. if (empty($this->streamQuery->sort)) { $this->streamQuery->sort = $this->sort; } $this->trigger(self::EVENT_BEFORE_APPLY_FILTERS); } /** * This function is called after the StreamQuery was build and all filters are applied. At this point changing * most StreamQuery settings as filters won't have any effect. Since the query is not yet executed the * StreamQuery->query() can still be used for custom query conditions. * * When overriding this method, make sure you call the parent implementation like the following: * * ```php * public function afterApplyFilters() * { * // Manipulate query... * * parent::afterApplyFilters(); * } * ``` * * When overriding this method, make sure you call the parent implementation at the beginning of your function. */ protected function afterApplyFilters() { $this->setDeprecatedActionProperties(); // Update action filters with merged request and configured action filters. $this->filters = $this->streamQuery->filters; $this->user = $this->streamQuery->user; if(!$this->streamEntryOptions) { $this->streamEntryOptions = $this->initStreamEntryOptions(); } if($this->streamEntryWidgetClass) { $this->streamEntryOptions->overwriteWidgetClass($this->streamEntryWidgetClass); } $this->trigger(self::EVENT_AFTER_APPLY_FILTERS); } /** * @return StreamEntryOptions */ protected function initStreamEntryOptions() { $instance = new StreamEntryOptions(); if($this->viewContext) { $instance->viewContext($this->viewContext); } return $instance; } /** * @inheritdoc * @throws \Throwable */ public function run() { $response = new StreamResponse($this->streamQuery); $entries = $this->streamQuery->all(); if(!empty($entries)) { $this->addResponseEntries($entries, $response); } else { $this->handleEmptyResponse($response); } $this->trigger(static::EVENT_AFTER_FETCH, new StreamResponseEvent(['response' => $response])); return $response->asJson(); } /** * Adds entries to the response. * * @param StreamResponse $response * @throws Exception * @throws \Throwable * @since 1.7 */ private function addResponseEntries($entries, StreamResponse $response) { foreach ($entries as $content) { $streamEntry = $this->getStreamEntryResult($content, $this->streamEntryOptions); if($streamEntry) { $response->addEntry($streamEntry); } } } /** * Adds an error message to the stream response in certain cases. * * @param StreamResponse $response * @throws Exception * @throws \Throwable * @since 1.7 */ private function handleEmptyResponse(StreamResponse $response) { if($this->streamQuery->isSingleContentQuery()) { $content = Content::findOne(['id' => $this->streamQuery->contentId]); if(!$content) { $response->setError(400, Yii::t('StreamModule.base', 'The content could not be found.')); } elseif (!$content->canView()) { $response->setError(403, Yii::t('StreamModule.base', 'You are not allowed to view this content.')); } } // Otherwise the content could not be found due to active filter } /** * @param Content $content * @param StreamEntryOptions|null $options * @return array|null * @throws \Throwable */ private function getStreamEntryResult(Content $content, StreamEntryOptions $options = null) { try { if (!$content->getModel()) { throw new Exception('Could not get contents underlying object! - contentid: ' . $content->id); } if (!is_subclass_of($content->getModel()->wallEntryClass, StreamEntryWidget::class, true)) { return static::getContentResultEntry($content); } return StreamEntryResponse::getAsArray($content, $options); } catch (\Throwable $e) { // Don't kill the stream action in prod environments in case the rendering of an entry fails. if (YII_ENV_PROD) { Yii::error($e); } else { throw $e; } } return null; } /** * @return StreamQuery */ public function getStreamQuery() { return $this->streamQuery; } /** * @return bool */ private function isSingleContentRequest() { if (Yii::$app->request->isConsoleRequest) { return false; } if (!(Yii::$app->request instanceof Request)) { return false; } $streamQueryParams = Yii::$app->request->getQueryParam('StreamQuery'); return !empty($streamQueryParams['contentId']); } }