Skip to content

Commit

Permalink
Merge pull request #14212 from jdalsem/activity-last-action
Browse files Browse the repository at this point in the history
feat(activity): commenting bumps related river activity last action
  • Loading branch information
jdalsem committed Nov 17, 2022
2 parents 3b52d0f + 00868b6 commit cd27191
Show file tree
Hide file tree
Showing 11 changed files with 176 additions and 17 deletions.
43 changes: 43 additions & 0 deletions engine/classes/Elgg/Comments/UpdateRiverLastActionHandler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

namespace Elgg\Comments;

/**
* Updates river item last action
*
* @since 5.0
*/
class UpdateRiverLastActionHandler {

/**
* Updates the last action of a related river item
*
* @param \Elgg\Event $event 'create:after', 'river'
*
* @return void
*/
public function __invoke(\Elgg\Event $event) {
$item = $event->getObject();
if (!$item instanceof \ElggRiverItem) {
return;
}

$object = $item->getObjectEntity();
if (!$object instanceof \ElggComment || $item->action_type !== 'comment') {
return;
}

// find create river and update the river item
$river = elgg_get_river([
'object_guid' => $item->target_guid,
'action' => 'create',
'limit' => 1,
]);
if (empty($river)) {
return;
}

$old_item = $river[0];
$old_item->updateLastAction($item->getTimePosted());
}
}
6 changes: 3 additions & 3 deletions engine/classes/Elgg/Database/EntityTable.php
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,7 @@ public function fetch(QueryBuilder $query, array $options = []) {
}

/**
* Update the last_action column in the entities table for $guid.
* Update the last_action column in the entities table for $entity.
*
* @warning This is different to time_updated. Time_updated is automatically set,
* while last_action is only set when explicitly called.
Expand All @@ -434,7 +434,7 @@ public function fetch(QueryBuilder $query, array $options = []) {
*
* @return int
*/
public function updateLastAction(\ElggEntity $entity, int $posted = null) {
public function updateLastAction(\ElggEntity $entity, int $posted = null): int {

if ($posted === null) {
$posted = $this->getCurrentTime()->getTimestamp();
Expand All @@ -457,7 +457,7 @@ public function updateLastAction(\ElggEntity $entity, int $posted = null) {
* @return \ElggUser|null
* @throws UserFetchFailureException
*/
public function getUserForPermissionsCheck($guid = 0) {
public function getUserForPermissionsCheck(int $guid = null): ?\ElggUser {
if (!$guid || $guid === $this->session->getLoggedInUserGuid()) {
return $this->session->getLoggedInUser();
}
Expand Down
24 changes: 24 additions & 0 deletions engine/classes/Elgg/Database/RiverTable.php
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ public function create(\ElggRiverItem $item): bool {
'target_guid' => $insert->param($item->target_guid ?? 0, ELGG_VALUE_GUID),
'annotation_id' => $insert->param($item->annotation_id ?? 0, ELGG_VALUE_ID),
'posted' => $insert->param($created, ELGG_VALUE_TIMESTAMP),
'last_action' => $insert->param($created, ELGG_VALUE_TIMESTAMP),
]);

$id = $this->db->insertData($insert);
Expand All @@ -145,6 +146,7 @@ public function create(\ElggRiverItem $item): bool {

$item->id = $id;
$item->posted = $created;
$item->last_action = $created;

$this->events->triggerAfter('create', 'river', $item);

Expand Down Expand Up @@ -176,4 +178,26 @@ public function delete(\ElggRiverItem $item): bool {

return $result;
}

/**
* Update the last_action column in the river table for $item.
*
* @param \ElggRiverItem $item River item to update
* @param int $last_action Timestamp of last action
*
* @return int
*/
public function updateLastAction(\ElggRiverItem $item, int $last_action = null): int {
if ($last_action === null) {
$last_action = $this->getCurrentTime()->getTimestamp();
}

$update = Update::table(self::TABLE_NAME);
$update->set('last_action', $update->param($last_action, ELGG_VALUE_TIMESTAMP))
->where($update->compare('id', '=', $item->id, ELGG_VALUE_ID));

$this->db->updateData($update);

return (int) $last_action;
}
}
12 changes: 6 additions & 6 deletions engine/classes/ElggEntity.php
Original file line number Diff line number Diff line change
Expand Up @@ -1864,15 +1864,15 @@ public function deleteOwnedAccessCollections() {
* while last_action is only set when explicitly called.
*
* @param int $posted Timestamp of last action
* @return int|false
* @return int
* @internal
*/
public function updateLastAction(int $posted = null): int|false {
public function updateLastAction(int $posted = null): int {
$posted = _elgg_services()->entityTable->updateLastAction($this, $posted);
if ($posted) {
$this->attributes['last_action'] = $posted;
$this->cache();
}

$this->attributes['last_action'] = $posted;
$this->cache();

return $posted;
}

Expand Down
30 changes: 23 additions & 7 deletions engine/classes/ElggRiverItem.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
* @property string $view The view for displaying this river item
* @property int $access_id The visibility of the river item
* @property int $posted UNIX timestamp when the action occurred
* @property int $last_action UNIX timestamp when the river item was bumped
*/
class ElggRiverItem {

Expand All @@ -26,6 +27,7 @@ class ElggRiverItem {
'annotation_id',
'access_id',
'posted',
'last_action',
];

/**
Expand Down Expand Up @@ -109,7 +111,7 @@ public function getAnnotation(): ?\ElggAnnotation {
*
* @return string
*/
public function getView() {
public function getView(): string {
return $this->view;
}

Expand All @@ -118,10 +120,23 @@ public function getView() {
*
* @return int
*/
public function getTimePosted() {
public function getTimePosted(): int {
return (int) $this->posted;
}

/**
* Update the last_action column in the river table.
*
* @param int $last_action Timestamp of last action
*
* @return int
*/
public function updateLastAction(int $last_action = null): int {
$this->last_action = _elgg_services()->riverTable->updateLastAction($this, $last_action);

return $this->last_action;
}

/**
* Get the type of the object
*
Expand All @@ -130,7 +145,7 @@ public function getTimePosted() {
*
* @return string 'river'
*/
public function getType() {
public function getType(): string {
return 'river';
}

Expand All @@ -141,7 +156,7 @@ public function getType() {
*
* @return string 'item'
*/
public function getSubtype() {
public function getSubtype(): string {
return 'item';
}

Expand All @@ -155,7 +170,7 @@ public function getSubtype() {
* @return bool Whether this river item should be considered deletable by the given user.
* @since 2.3
*/
public function canDelete($user_guid = 0) {
public function canDelete(int $user_guid = 0): bool {
return _elgg_services()->userCapabilities->canDeleteRiverItem($this, $user_guid);
}

Expand All @@ -165,7 +180,7 @@ public function canDelete($user_guid = 0) {
* @return bool False if the user lacks permission or the before event is cancelled
* @since 2.3
*/
public function delete() {
public function delete(): bool {
if (!$this->canDelete()) {
return false;
}
Expand All @@ -178,7 +193,7 @@ public function delete() {
*
* @return \stdClass
*/
public function toObject() {
public function toObject(): \stdClass {
$object = new \stdClass();
$object->id = $this->id;
$object->subject_guid = $this->subject_guid;
Expand All @@ -189,6 +204,7 @@ public function toObject() {
$object->action = $this->action_type;
$object->view = $this->view;
$object->time_posted = date('c', $this->getTimePosted());
$object->last_action = date('c', $this->last_action);

$params = ['item' => $this];
return _elgg_services()->events->triggerResults('to:object', 'river_item', $params, $object);
Expand Down
2 changes: 1 addition & 1 deletion engine/classes/ElggSite.php
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ public function getEmailAddress(): string {
/**
* {@inheritDoc}
*/
public function updateLastAction(int $posted = null): int|false {
public function updateLastAction(int $posted = null): int {
// setting last action on ElggSite makes no sense... just returning current value to be compliant
return $this->last_action;
}
Expand Down
1 change: 1 addition & 0 deletions engine/events.php
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@
],
'create:after' => [
'river' => [
\Elgg\Comments\UpdateRiverLastActionHandler::class => [],
\Elgg\River\UpdateLastActionHandler::class => [],
],
],
Expand Down
34 changes: 34 additions & 0 deletions engine/schema/migrations/20221110111653_add_river_last_action.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php
declare(strict_types=1);

use Phinx\Migration\AbstractMigration;
use Phinx\Db\Adapter\MysqlAdapter;

final class AddRiverLastAction extends AbstractMigration {
/**
* Adds the river last action column and fills it with the posted timestamp
*/
public function change(): void {
$table = $this->table('river');
if ($table->hasColumn('last_action')) {
return;
}

$table->addColumn('last_action', 'integer', [
'null' => false,
'limit' => MysqlAdapter::INT_REGULAR,
'precision' => 11,
]);
$table->addIndex(['last_action'], [
'name' => 'last_action',
'unique' => false,
]);

$table->update();

// copy posted into last_action
$prefix = $this->getAdapter()->getOption('table_prefix');

$this->execute("UPDATE {$prefix}river SET last_action = posted");
}
}
18 changes: 18 additions & 0 deletions engine/tests/phpunit/integration/ElggRiverItemIntegrationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,24 @@ public function testGetTimePosted() {
$this->assertLessThanOrEqual(time(), $item->getTimePosted());
}

public function testLastActionOnCreate() {
$item = $this->getRiverItem();

$this->assertIsInt($item->last_action);
$this->assertEquals($item->getTimePosted(), $item->last_action);
}

public function testUpdateLastAction() {
$item = $this->getRiverItem();

$new_last_action = $item->last_action + 100;
$item->updateLastAction($new_last_action);
$this->assertEquals($new_last_action, $item->last_action);

$loaded_item = elgg_get_river_item_from_id($item->id);
$this->assertEquals($new_last_action, $loaded_item->last_action);
}

public function testCanDelete() {
$item = $this->getRiverItem();

Expand Down
6 changes: 6 additions & 0 deletions mod/activity/views/default/resources/activity/all.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
* Show all site river activity
*/

use Elgg\Database\Clauses\OrderByClause;

// get filter options
$type = preg_replace('[\W]', '', get_input('type', 'all'));
$subtype = preg_replace('[\W]', '', get_input('subtype', ''));
Expand All @@ -12,6 +14,10 @@
'entity_type' => $type,
'entity_subtype' => $subtype,
'show_filter' => true,
'show_comments' => false,
'options' => [
'order_by' => new OrderByClause('last_action', 'DESC'),
],
]);

// draw page
Expand Down
17 changes: 17 additions & 0 deletions mod/activity/views/default/river/listing/all.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,27 @@
* @uses $vars['show_filter'] Add river filter selector (default: false)
*/

use Elgg\Database\QueryBuilder;

// filter
$show_filter = (bool) elgg_extract('show_filter', $vars, false);
unset($vars['show_filter']);
if ($show_filter) {
echo elgg_view('river/filter', $vars);
}

// determines if individual comments show in the listing
$show_comments = (bool) elgg_extract('show_comments', $vars, true);
unset($vars['show_comments']);

// activity
$defaults = [
'distinct' => false,
'no_results' => elgg_echo('river:none'),
'pagination_previous_text' => elgg_echo('newer'),
'pagination_next_text' => elgg_echo('older'),
'pagination_show_numbers' => false,
'wheres' => [],
];

$options = (array) elgg_extract('options', $vars, []);
Expand All @@ -33,6 +40,16 @@
if (!empty($entity_subtype)) {
$options['subtype'] = $entity_subtype;
}
} elseif (!$show_comments) {
$options['wheres'][] = function (QueryBuilder $qb, $main_alias) {
$alias = $qb->joinEntitiesTable($main_alias, 'object_guid', 'inner', 'oe');
$types = [
$qb->compare("{$alias}.type", '=', 'object', ELGG_VALUE_STRING),
$qb->compare("{$alias}.subtype", '=', 'comment', ELGG_VALUE_STRING),
];

return 'NOT (' . $qb->merge($types, 'AND') . ')';
};
}

echo elgg_list_river($options);

0 comments on commit cd27191

Please sign in to comment.