Добавление "лайков" к новостям

Материал из Umicms
Перейти к:навигация, поиск

Актуально для версии 20.

Задача: добавить к новости возможность ставить "лайк" и выводить новости в лентах по принципу "чем больше лайков - тем выше новость".

Решение:

  • 1. В типе данных "Новость" создаём новую группу полей и в ней поле типа "Счётчик", ответственное за лайки. Для примера назовём его likes.
  • 2. Напишем кастомные макросы для работы с этим полем в файле ~/classes/components/news/customMacros.php:
// Ставит лайк, инкрементирует их число
public function addLike($current_page_id) {
    $hierarchy = umiHierarchy::getInstance();
    $element = $hierarchy->getElement($current_page_id);
    $temp_count = $element->getValue("likes");
    ++$temp_count;
    $element->setValue("likes",$temp_count);
    $element->commit();
}
 
// Для отображения лайков на странице, возвращает их кол-во
public function getLikesCount($current_page_id) {
    $hierarchy = umiHierarchy::getInstance();
    $element = $hierarchy->getElement($current_page_id);
    return $element->getValue("likes");
}

3. Затем, нужно переопределить метод вывода новостей lastlist, его код можно взять в файле macros.php в той же папке news. Он довольно большой, но нам будет достаточно поставить только одну строчку $news->order('likes')->desc(); после строк:

 
$news = new selector('pages');
$news->types('hierarchy-type')->name('news', 'item');

Когда все методы реализованы, остаётся только вставить макросы addLike и getLikesCount в нужные места в шаблонах сайта. При нажатии кнопки "Лайк" посылаем ajax-запрос на /news/addLike/<идентификатор страницы> и обновляем значение лайков на странице.

После всех этих действий новости будут выводится по принципу "чем больше лайков - тем выше новость".

Код метода lastlist:

public function lastlist(
			$path = '',
			$template = 'default',
			$per_page = false,
			$ignore_paging = false,
			$sDaysInterval = '',
			$bSkipOrderByTime = false,
			$level = 1
		) {
			if (!$per_page) {
				$per_page = $this->module->per_page;
			}

			$per_page = (int) $per_page;
			$sDaysInterval = (string) $sDaysInterval;

			if ($sDaysInterval !== '') {
				$sStartDaysOffset = '';
				$sFinishDaysOffset = '';
				$arrDaysInterval = preg_split("/\s+/is", $sDaysInterval);
				if (isset($arrDaysInterval[0])) {
					$sStartDaysOffset = $arrDaysInterval[0];
				}
				if (isset($arrDaysInterval[1])) {
					$sFinishDaysOffset = $arrDaysInterval[1];
				}

				$iNowTime = time();

				if ($sStartDaysOffset === '+') {
					$iStartDaysOffset = (PHP_INT_MAX - $iNowTime);
				} elseif ($sStartDaysOffset === '-') {
					$iStartDaysOffset = (0 - PHP_INT_MAX + $iNowTime);
				} else {
					$iStartDaysOffset = (int) $sStartDaysOffset;
					$sPostfix = mb_substr($sStartDaysOffset, -1);

					if ($sPostfix === 'm') {
						$iStartDaysOffset *= 60;
					} elseif ($sPostfix === 'h' || $sPostfix === 'H') {
						$iStartDaysOffset *= (60 * 60);
					} else {
						$iStartDaysOffset *= (60 * 60 * 24);
					}
				}

				if ($sFinishDaysOffset === '+') {
					$iFinishDaysOffset = (PHP_INT_MAX - $iNowTime);
				} elseif ($sFinishDaysOffset === '-') {
					$iFinishDaysOffset = (0 - PHP_INT_MAX + $iNowTime);
				} else {
					$iFinishDaysOffset = (int) $sFinishDaysOffset;
					$sPostfix = mb_substr($sFinishDaysOffset, -1);

					if ($sPostfix === 'm') {
						$iFinishDaysOffset *= 60;
					} elseif ($sPostfix === 'h' || $sPostfix === 'H') {
						$iFinishDaysOffset *= (60 * 60);
					} else {
						$iFinishDaysOffset *= (60 * 60 * 24);
					}
				}

				$iPeriodStart = $iNowTime + $iStartDaysOffset;
				$iPeriodFinish = $iNowTime + $iFinishDaysOffset;
				$bPeriodOrder = ($iPeriodStart < $iPeriodFinish);
			} else {
				$iPeriodStart = false;
				$iPeriodFinish = false;
				$bPeriodOrder = false;
			}

			$curr_page = (int) getRequest('p');
			if ($ignore_paging) {
				$curr_page = 0;
			}

			$parentId = $this->module->analyzeRequiredPath($path);
			if ($parentId === false && $path != KEYWORD_GRAB_ALL) {
				throw new publicException(getLabel('error-page-does-not-exist', null, $path));
			}

			$umiLinksHelper = umiLinksHelper::getInstance();
			$umiLinksHelper->loadLinkPartForPages([$parentId]);

			$month = (int) getRequest('month');
			$year = (int) getRequest('year');
			$day = (int) getRequest('day');

			$news = new selector('pages');
			$news->types('hierarchy-type')->name('news', 'item');
			// Добавляем сортировку по лайкам
			$news->order('likes')->desc();

			if ($path != KEYWORD_GRAB_ALL) {
				$escapedLevel = (int) $level;
				$escapedLevel = ($escapedLevel === 0) ? 1 : $escapedLevel;

				if (is_array($parentId)) {
					foreach ($parentId as $parent) {
						$news->where('hierarchy')->page($parent)->level($escapedLevel);
					}
				} else {
					$news->where('hierarchy')->page($parentId)->level($escapedLevel);
				}
			}

			if (!empty($month) && !empty($year) && !empty($day)) {
				$date1 = mktime(0, 0, 0, $month, $day, $year);
				$date2 = mktime(23, 59, 59, $month, $day, $year);
				$news->where('publish_time')->between($date1, $date2);
			} elseif (!empty($month) && !empty($year)) {
				$date1 = mktime(0, 0, 0, $month, 1, $year);
				$date2 = mktime(23, 59, 59, $month + 1, 0, $year);
				$news->where('publish_time')->between($date1, $date2);
			} elseif (!empty($year)) {
				$date1 = mktime(0, 0, 0, 1, 1, $year);
				$date2 = mktime(23, 59, 59, 12, 31, $year);
				$news->where('publish_time')->between($date1, $date2);
			} elseif ($iPeriodStart !== $iPeriodFinish) {
				if ($iPeriodStart && $iPeriodFinish) {
					if ($sDaysInterval && $sDaysInterval != '+ -') {
						if ($iPeriodStart < $iPeriodFinish) {
							$news->where('publish_time')->between($iPeriodStart, $iPeriodFinish);
						} else {
							$news->where('publish_time')->between($iPeriodFinish, $iPeriodStart);
						}
					}
				}
			}

			if (!$bSkipOrderByTime) {
				if ($bPeriodOrder === true) {
					$news->order('publish_time')->asc();
				} else {
					$news->order('publish_time')->desc();
				}
			}

			selectorHelper::detectFilters($news);
			$news->option('load-all-props')->value(true);
			$news->limit($curr_page * $per_page, $per_page);

			$result = $news->result();
			$total = $news->length();

			$umiHierarchy = umiHierarchy::getInstance();
			$moduleClass = $this->module;

			list(
				$template_block,
				$template_block_empty,
				$template_line,
				$template_archive
				) = $moduleClass::loadTemplates(
				'news/' . $template,
				'lastlist_block',
				'lastlist_block_empty',
				'lastlist_item',
				'lastlist_archive'
			);

			if (umiCount($result) == 0) {
				return $moduleClass::parseTemplate($template_block_empty, []);
			}

			$block_arr = [];
			$lines = [];

			foreach ($result as $element) {
				if (!$element instanceof iUmiHierarchyElement) {
					continue;
				}

				$element_id = $element->getId();

				$line_arr = [];
				$line_arr['attribute:id'] = $element_id;
				$line_arr['node:name'] = $element->getName();
				$line_arr['attribute:link'] = $umiLinksHelper->getLinkByParts($element);
				$line_arr['xlink:href'] = 'upage://' . $element_id;
				$line_arr['void:header'] = $lines_arr['name'] = $element->getName();

				$publish_time = $element->getValue('publish_time');
				if ($publish_time) {
					$line_arr['attribute:publish_time'] = $publish_time->getFormattedDate('U');
				}

				$lent_name = '';
				$lent_link = '';
				$lent_id = $element->getParentId();

				$lent_element = $umiHierarchy->getElement($lent_id);
				if ($lent_element) {
					$lent_name = $lent_element->getName();
					$lent_link = $umiLinksHelper->getLinkByParts($lent_element);
				}

				$line_arr['attribute:lent_id'] = $lent_id;
				$line_arr['attribute:lent_name'] = $lent_name;
				$line_arr['attribute:lent_link'] = $lent_link;

				$lines[] = $moduleClass::parseTemplate($template_line, $line_arr, $element_id);
				$moduleClass::pushEditable('news', 'item', $element_id);
				$umiHierarchy->unloadElement($element_id);
			}

			if (is_array($parentId)) {
				list($parentId) = $parentId;
			}

			$block_arr['subnodes:items'] = $block_arr['void:lines'] = $lines;
			$block_arr['archive'] = ($total > 0) ? $template_archive : '';
			$parent = $umiHierarchy->getElement($parentId);

			if ($parent instanceof iUmiHierarchyElement) {
				$block_arr['archive_link'] = $umiLinksHelper->getLinkByParts($parent);
			}

			$block_arr['total'] = $total;
			$block_arr['per_page'] = $per_page;
			$block_arr['category_id'] = $parentId;

			return $moduleClass::parseTemplate($template_block, $block_arr, $parentId);
		}