123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360 |
- <?php
- /**
- * Elgg comments library
- *
- * @package Elgg.Core
- * @subpackage Comments
- * @since 1.9
- */
- /**
- * Comments initialization function
- *
- * @return void
- * @access private
- */
- function _elgg_comments_init() {
- elgg_register_entity_type('object', 'comment');
- elgg_register_plugin_hook_handler('register', 'menu:entity', '_elgg_comment_setup_entity_menu', 900);
- elgg_register_plugin_hook_handler('entity:url', 'object', '_elgg_comment_url_handler');
- elgg_register_plugin_hook_handler('container_permissions_check', 'object', '_elgg_comments_container_permissions_override');
- elgg_register_plugin_hook_handler('permissions_check', 'object', '_elgg_comments_permissions_override');
- elgg_register_plugin_hook_handler('email', 'system', '_elgg_comments_notification_email_subject');
-
- elgg_register_event_handler('update:after', 'all', '_elgg_comments_access_sync');
- elgg_register_page_handler('comment', '_elgg_comments_page_handler');
- elgg_register_ajax_view('core/ajax/edit_comment');
- }
- /**
- * Page handler for generic comments manipulation.
- *
- * @param array $page
- * @return bool
- * @access private
- */
- function _elgg_comments_page_handler($page) {
- switch ($page[0]) {
- case 'edit':
- elgg_gatekeeper();
- if (empty($page[1])) {
- register_error(elgg_echo('generic_comment:notfound'));
- forward(REFERER);
- }
- $comment = get_entity($page[1]);
- if (!($comment instanceof \ElggComment) || !$comment->canEdit()) {
- register_error(elgg_echo('generic_comment:notfound'));
- forward(REFERER);
- }
- $target = $comment->getContainerEntity();
- if (!($target instanceof \ElggEntity)) {
- register_error(elgg_echo('generic_comment:notfound'));
- forward(REFERER);
- }
- $title = elgg_echo('generic_comments:edit');
- elgg_push_breadcrumb($target->getDisplayName(), $target->getURL());
- elgg_push_breadcrumb($title);
- $params = array(
- 'entity' => $target,
- 'comment' => $comment,
- 'is_edit_page' => true,
- );
- $content = elgg_view_form('comment/save', null, $params);
- $params = array(
- 'content' => $content,
- 'title' => $title,
- 'filter' => '',
- );
- $body = elgg_view_layout('content', $params);
- echo elgg_view_page($title, $body);
- return true;
- break;
- case 'view':
- _elgg_comment_redirect(elgg_extract(1, $page), elgg_extract(2, $page));
- break;
- default:
- return false;
- break;
- }
- }
- /**
- * Redirect to the comment in context of the containing page
- *
- * @param int $comment_guid GUID of the comment
- * @param int $fallback_guid GUID of the containing entity
- *
- * @return void
- * @access private
- */
- function _elgg_comment_redirect($comment_guid, $fallback_guid) {
- $fail = function () {
- register_error(elgg_echo('generic_comment:notfound'));
- forward(REFERER);
- };
- $comment = get_entity($comment_guid);
- if (!$comment) {
- // try fallback if given
- $fallback = get_entity($fallback_guid);
- if (!$fallback) {
- $fail();
- }
- register_error(elgg_echo('generic_comment:notfound_fallback'));
- forward($fallback->getURL());
- }
- if (!elgg_instanceof($comment, 'object', 'comment')) {
- $fail();
- }
- $container = $comment->getContainerEntity();
- if (!$container) {
- $fail();
- }
- // this won't work with threaded comments, but core doesn't support that yet
- $count = elgg_get_entities([
- 'type' => 'object',
- 'subtype' => 'comment',
- 'container_guid' => $container->guid,
- 'count' => true,
- 'wheres' => ["e.guid < " . (int)$comment->guid],
- ]);
- $limit = (int)get_input('limit');
- if (!$limit) {
- $limit = elgg_trigger_plugin_hook('config', 'comments_per_page', [], 25);
- }
- $offset = floor($count / $limit) * $limit;
- if (!$offset) {
- $offset = null;
- }
- $url = elgg_http_add_url_query_elements($container->getURL(), [
- 'offset' => $offset,
- ]) . "#elgg-object-{$comment->guid}";
- forward($url);
- }
- /**
- * Setup the menu shown with a comment
- *
- * @param string $hook 'register'
- * @param string $type 'menu:entity'
- * @param \ElggMenuItem[] $return Array of \ElggMenuItem objects
- * @param array $params Array of view vars
- *
- * @return array
- * @access private
- */
- function _elgg_comment_setup_entity_menu($hook, $type, $return, $params) {
- if (elgg_in_context('widgets')) {
- return $return;
- }
- $entity = $params['entity'];
- if (!elgg_instanceof($entity, 'object', 'comment')) {
- return $return;
- }
- // Remove edit link and access level from the menu
- foreach ($return as $key => $item) {
- if ($item->getName() === 'access') {
- unset($return[$key]);
- }
- }
- return $return;
- }
- /**
- * Format and return the URL for a comment.
- *
- * This is the container's URL because comments don't have their own page.
- *
- * @param string $hook 'entity:url'
- * @param string $type 'object'
- * @param string $return URL for entity
- * @param array $params Array with the elgg entity passed in as 'entity'
- *
- * @return string
- * @access private
- */
- function _elgg_comment_url_handler($hook, $type, $return, $params) {
- $entity = $params['entity'];
- /* @var \ElggObject $entity */
- if (!elgg_instanceof($entity, 'object', 'comment') || !$entity->getOwnerEntity()) {
- // not a comment or has no owner
- // @todo handle anonymous comments
- return $return;
- }
- $container = $entity->getContainerEntity();
- if (!$container) {
- return $return;
- }
- return "comment/view/{$entity->guid}/{$container->guid}";
- }
- /**
- * Allow users to comment on entities not owned by them.
- *
- * Object being commented on is used as the container of the comment so
- * permission check must be overridden if user isn't the owner of the object.
- *
- * @param string $hook 'container_permissions_check'
- * @param string $type 'object'
- * @param boolean $return Can the current user write to this container?
- * @param array $params Array of parameters (container, user, subtype)
- *
- * @return array
- * @access private
- * @todo this doesn't seem to make a difference if a user can comment or not
- */
- function _elgg_comments_container_permissions_override($hook, $type, $return, $params) {
- // is someone trying to comment, if so override permissions check
- if ($params['subtype'] === 'comment') {
- return true;
- }
- return $return;
- }
- /**
- * By default, only authors can edit their comments.
- *
- * @param string $hook 'permissions_check'
- * @param string $type 'object'
- * @param boolean $return Can the given user edit the given entity?
- * @param array $params Array of parameters (entity, user)
- *
- * @return boolean Whether the given user is allowed to edit the given comment.
- */
- function _elgg_comments_permissions_override($hook, $type, $return, $params) {
- $entity = $params['entity'];
- $user = $params['user'];
-
- if (elgg_instanceof($entity, 'object', 'comment') && $user) {
- return $entity->getOwnerGUID() == $user->getGUID();
- }
-
- return $return;
- }
- /**
- * Set subject for email notifications about new ElggComment objects
- *
- * The "Re: " part is required by some email clients in order to properly
- * group the notifications in threads.
- *
- * Group discussion replies extend ElggComment objects so this takes care
- * of their notifications also.
- *
- * @param string $hook 'email'
- * @param string $type 'system'
- * @param array $returnvalue Current mail parameters
- * @param array $params Original mail parameters
- * @return array $returnvalue Modified mail parameters
- */
- function _elgg_comments_notification_email_subject($hook, $type, $returnvalue, $params) {
- if (!is_array($returnvalue)) {
- // another hook handler returned a non-array, let's not override it
- return;
- }
- /** @var Elgg\Notifications\Notification */
- $notification = elgg_extract('notification', $returnvalue['params']);
- if ($notification instanceof Elgg\Notifications\Notification) {
- $object = elgg_extract('object', $notification->params);
- if ($object instanceof ElggComment) {
- $container = $object->getContainerEntity();
- $returnvalue['subject'] = 'Re: ' . $container->getDisplayName();
- }
- }
- return $returnvalue;
- }
- /**
- * Update comment access to match that of the container
- *
- * @param string $event 'update:after'
- * @param string $type 'all'
- * @param ElggEntity $entity The updated entity
- * @return bool
- *
- * @access private
- */
- function _elgg_comments_access_sync($event, $type, $entity) {
- if (!($entity instanceof \ElggEntity)) {
- return true;
- }
-
- // need to override access in case comments ended up with ACCESS_PRIVATE
- // and to ensure write permissions
- $ia = elgg_set_ignore_access(true);
- $options = array(
- 'type' => 'object',
- 'subtype' => 'comment',
- 'container_guid' => $entity->getGUID(),
- 'wheres' => array(
- "e.access_id != {$entity->access_id}"
- ),
- 'limit' => 0,
- );
- $batch = new \ElggBatch('elgg_get_entities', $options, null, 25, false);
- foreach ($batch as $comment) {
- // Update comment access_id
- $comment->access_id = $entity->access_id;
- $comment->save();
- }
-
- elgg_set_ignore_access($ia);
-
- return true;
- }
- /**
- * Runs unit tests for \ElggComment
- *
- * @param string $hook unit_test
- * @param string $type system
- * @param mixed $value Array of tests
- * @param mixed $params Params
- *
- * @return array
- * @access private
- */
- function _elgg_comments_test($hook, $type, $value, $params) {
- global $CONFIG;
- $value[] = "{$CONFIG->path}engine/tests/ElggCommentTest.php";
- return $value;
- }
- return function(\Elgg\EventsService $events, \Elgg\HooksRegistrationService $hooks) {
- $events->registerHandler('init', 'system', '_elgg_comments_init');
- $hooks->registerHandler('unit_test', 'system', '_elgg_comments_test');
- };
|