Page MenuHomestyx hydra

No OneTemporary

diff --git a/src/applications/feed/PhabricatorFeedQuery.php b/src/applications/feed/PhabricatorFeedQuery.php
index d51898e5ce..00ca3fcbec 100644
--- a/src/applications/feed/PhabricatorFeedQuery.php
+++ b/src/applications/feed/PhabricatorFeedQuery.php
@@ -1,132 +1,113 @@
<?php
/*
* Copyright 2012 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
final class PhabricatorFeedQuery {
private $filterPHIDs;
private $limit = 100;
private $after;
private $before;
public function setFilterPHIDs(array $phids) {
$this->filterPHIDs = $phids;
return $this;
}
public function setLimit($limit) {
$this->limit = $limit;
return $this;
}
public function setAfter($after) {
$this->after = $after;
return $this;
}
public function setBefore($before) {
$this->before = $before;
return $this;
}
public function execute() {
$ref_table = new PhabricatorFeedStoryReference();
$story_table = new PhabricatorFeedStoryData();
$conn = $story_table->establishConnection('r');
$where = array();
if ($this->filterPHIDs) {
$where[] = qsprintf(
$conn,
'ref.objectPHID IN (%Ls)',
$this->filterPHIDs);
}
// For "before" queries, we can just add a constraint to the WHERE clause.
// For "after" queries, we must also reverse the result ordering, since
// otherwise we'll always grab the first page of results if there's a limit.
// After MySQL applies the limit, we reverse the page in PHP (below) to
// ensure consistent ordering.
$order = 'DESC';
if ($this->after) {
$where[] = qsprintf(
$conn,
'ref.chronologicalKey > %s',
$this->after);
$order = 'ASC';
}
if ($this->before) {
$where[] = qsprintf(
$conn,
'ref.chronologicalKey < %s',
$this->before);
}
if ($where) {
$where = 'WHERE ('.implode(') AND (', $where).')';
} else {
$where = '';
}
$data = queryfx_all(
$conn,
'SELECT story.* FROM %T ref
JOIN %T story ON ref.chronologicalKey = story.chronologicalKey
%Q
GROUP BY ref.chronologicalKey
ORDER BY ref.chronologicalKey %Q
LIMIT %d',
$ref_table->getTableName(),
$story_table->getTableName(),
$where,
$order,
$this->limit);
if ($order != 'DESC') {
// If we did order ASC to pull 'after' data, reverse the result set so
// that stories are returned in a consistent (descending) order.
$data = array_reverse($data);
}
- $data = $story_table->loadAllFromArray($data);
-
- $stories = array();
- foreach ($data as $story_data) {
- $class = $story_data->getStoryType();
-
- try {
- if (!class_exists($class) ||
- !is_subclass_of($class, 'PhabricatorFeedStory')) {
- $class = 'PhabricatorFeedStoryUnknown';
- }
- } catch (PhutilMissingSymbolException $ex) {
- // If the class can't be loaded, libphutil will throw an exception.
- // Render the story using the unknown story view.
- $class = 'PhabricatorFeedStoryUnknown';
- }
-
- $stories[] = newv($class, array($story_data));
- }
-
- return $stories;
+ return PhabricatorFeedStory::loadAllFromRows($data);
}
+
}
diff --git a/src/applications/feed/story/PhabricatorFeedStory.php b/src/applications/feed/story/PhabricatorFeedStory.php
index d9ae34d3d1..eb5e54a196 100644
--- a/src/applications/feed/story/PhabricatorFeedStory.php
+++ b/src/applications/feed/story/PhabricatorFeedStory.php
@@ -1,146 +1,197 @@
<?php
/*
* Copyright 2012 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+/**
+ * Manages rendering and aggregation of a story. A story is an event (like a
+ * user adding a comment) which may be represented in different forms on
+ * different channels (like feed, notifications and realtime alerts).
+ *
+ * @task load Loading Stories
+ */
abstract class PhabricatorFeedStory {
private $data;
private $hasViewed;
private $handles;
private $framed;
private $primaryObjectPHID;
+
+/* -( Loading Stories )---------------------------------------------------- */
+
+
+ /**
+ * Given @{class:PhabricatorFeedStoryData} rows, load them into objects and
+ * construct appropriate @{class:PhabricatorFeedStory} wrappers for each
+ * data row.
+ *
+ * @param list<dict> List of @{class:PhabricatorFeedStoryData} rows from the
+ * database.
+ * @return list<PhabricatorFeedStory> List of @{class:PhabricatorFeedStory}
+ * objects.
+ * @task load
+ */
+ public static function loadAllFromRows(array $rows) {
+ $stories = array();
+
+ $data = id(new PhabricatorFeedStoryData())->loadAllFromArray($rows);
+ foreach ($data as $story_data) {
+ $class = $story_data->getStoryType();
+
+ $ok = false;
+ try {
+ $ok = is_subclass_of($class, 'PhabricatorFeedStory');
+ } catch (PhutilMissingSymbolException $ex) {
+ $ok = false;
+ }
+
+ // If the story type isn't a valid class or isn't a subclass of
+ // PhabricatorFeedStory, load it as PhabricatorFeedStoryUnknown.
+
+ if (!$ok) {
+ $class = 'PhabricatorFeedStoryUnknown';
+ }
+
+ $key = $story_data->getChronologicalKey();
+ $stories[$key] = newv($class, array($story_data));
+ }
+
+ return $stories;
+ }
+
+
public function setPrimaryObjectPHID($primary_object_phid) {
$this->primaryObjectPHID = $primary_object_phid;
return $this;
}
public function getPrimaryObjectPHID() {
return $this->primaryObjectPHID;
}
final public function __construct(PhabricatorFeedStoryData $data) {
$this->data = $data;
}
abstract public function renderView();
// TODO: Make abstract once all subclasses implement it.
public function renderNotificationView() {
return id(new PhabricatorFeedStoryUnknown($this->data))
->renderNotificationView();
}
public function getRequiredHandlePHIDs() {
return array();
}
public function setHasViewed($has_viewed) {
$this->hasViewed = $has_viewed;
return $this;
}
public function getHasViewed() {
return $this->hasViewed;
}
public function getRequiredObjectPHIDs() {
return array();
}
final public function setFramed($framed) {
$this->framed = $framed;
return $this;
}
final public function setHandles(array $handles) {
assert_instances_of($handles, 'PhabricatorObjectHandle');
$this->handles = $handles;
return $this;
}
final protected function getHandles() {
return $this->handles;
}
final protected function getHandle($phid) {
if (isset($this->handles[$phid])) {
if ($this->handles[$phid] instanceof PhabricatorObjectHandle) {
return $this->handles[$phid];
}
}
$handle = new PhabricatorObjectHandle();
$handle->setPHID($phid);
$handle->setName("Unloaded Object '{$phid}'");
return $handle;
}
final public function getStoryData() {
return $this->data;
}
final public function getEpoch() {
return $this->getStoryData()->getEpoch();
}
final public function getChronologicalKey() {
return $this->getStoryData()->getChronologicalKey();
}
final protected function renderHandleList(array $phids) {
$list = array();
foreach ($phids as $phid) {
$list[] = $this->linkTo($phid);
}
return implode(', ', $list);
}
final protected function linkTo($phid) {
$handle = $this->getHandle($phid);
// NOTE: We render our own link here to customize the styling and add
// the '_top' target for framed feeds.
return phutil_render_tag(
'a',
array(
'href' => $handle->getURI(),
'target' => $this->framed ? '_top' : null,
),
phutil_escape_html($handle->getLinkName()));
}
final protected function renderString($str) {
return '<strong>'.phutil_escape_html($str).'</strong>';
}
final protected function renderSummary($text, $len = 128) {
if ($len) {
$text = phutil_utf8_shorten($text, $len);
}
$text = phutil_escape_html($text);
$text = str_replace("\n", '<br />', $text);
return $text;
}
public function getNotificationAggregations() {
return array();
}
}
diff --git a/src/applications/notification/PhabricatorNotificationQuery.php b/src/applications/notification/PhabricatorNotificationQuery.php
index 9c1df89ff7..fcaaf62223 100644
--- a/src/applications/notification/PhabricatorNotificationQuery.php
+++ b/src/applications/notification/PhabricatorNotificationQuery.php
@@ -1,138 +1,124 @@
<?php
/*
* Copyright 2012 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @task config Configuring the Query
* @task exec Query Execution
*/
final class PhabricatorNotificationQuery extends PhabricatorOffsetPagedQuery {
private $userPHID;
private $keys;
private $unread;
/* -( Configuring the Query )---------------------------------------------- */
public function setUserPHID($user_phid) {
$this->userPHID = $user_phid;
return $this;
}
public function withKeys(array $keys) {
$this->keys = $keys;
return $this;
}
/**
* Filter results by read/unread status. Note that `true` means to return
* only unread notifications, while `false` means to return only //read//
* notifications. The default is `null`, which returns both.
*
* @param mixed True or false to filter results by read status. Null to remove
* the filter.
* @return this
* @task config
*/
public function withUnread($unread) {
$this->unread = $unread;
return $this;
}
/* -( Query Execution )---------------------------------------------------- */
public function execute() {
if (!$this->userPHID) {
throw new Exception("Call setUser() before executing the query");
}
$story_table = new PhabricatorFeedStoryData();
$notification_table = new PhabricatorFeedStoryNotification();
$conn = $story_table->establishConnection('r');
$data = queryfx_all(
$conn,
"SELECT story.*, notif.primaryObjectPHID, notif.hasViewed FROM %T notif
JOIN %T story ON notif.chronologicalKey = story.chronologicalKey
%Q
ORDER BY notif.chronologicalKey DESC
%Q",
$notification_table->getTableName(),
$story_table->getTableName(),
$this->buildWhereClause($conn),
$this->buildLimitClause($conn));
$viewed_map = ipull($data, 'hasViewed', 'chronologicalKey');
$primary_map = ipull($data, 'primaryObjectPHID', 'chronologicalKey');
- $data = $story_table->loadAllFromArray($data);
-
- $stories = array();
-
- foreach ($data as $story_data) {
- $class = $story_data->getStoryType();
- try {
- if (!class_exists($class) ||
- !is_subclass_of($class, 'PhabricatorFeedStory')) {
- $class = 'PhabricatorFeedStoryUnknown';
- }
- } catch (PhutilMissingSymbolException $ex) {
- $class = 'PhabricatorFeedStoryUnknown';
- }
- $story = newv($class, array($story_data));
- $story->setHasViewed($viewed_map[$story->getChronologicalKey()]);
- $story->setPrimaryObjectPHID($primary_map[$story->getChronologicalKey()]);
- $stories[] = $story;
+ $stories = PhabricatorFeedStory::loadAllFromRows($data);
+ foreach ($stories as $key => $story) {
+ $story->setHasViewed($viewed_map[$key]);
+ $story->setPrimaryObjectPHID($primary_map[$key]);
}
return $stories;
}
private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
$where = array();
if ($this->userPHID) {
$where[] = qsprintf(
$conn_r,
'notif.userPHID = %s',
$this->userPHID);
}
if ($this->unread !== null) {
$where[] = qsprintf(
$conn_r,
'notif.hasViewed = %d',
(int)!$this->unread);
}
if ($this->keys) {
$where[] = qsprintf(
$conn_r,
'notif.chronologicalKey IN (%Ls)',
$this->keys);
}
return $this->formatWhereClause($where);
}
}

File Metadata

Mime Type
text/x-diff
Expires
Tue, Mar 17, 2:08 AM (8 h, 30 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
964228
Default Alt Text
(13 KB)

Event Timeline