Журнал пользователя движка phpFOX 3

Переписал пагинацию для комментариев. Исправил небольшие недоработки и так же сделал пагинацию для ответов на комменты. С "завода" у ответов не было пагинации, они раскрывались сразу все. То есть, если будет у коммента 4500 ответов, сценарий будет пытаться отобразить их все. Я это исправил, теперь открывает по 10 штук по клику, в обратном порядке.
Сделал догрузку уведомлений, как для блока, что появляется при клике на значок уведомлений, так и на странице уведомлениях. И тут столкнулся с проблемой:
  1. Догрузка уведомлений полной версии на смартфоне не подгружает новые уведомления.
  2. В блоке уведомлений, после догрузки уведомлений, ссылка "Посмотреть все уведомления" может быть недоступна.

Очень может быть, что ссылку "Посмотреть все уведомления" прикрывает какой то невидимый элемент, я пока с этим не разобрался. К тому же, мне не удалось отловить, после каких действий такое происходит. Ошибка может проявиться, а может и нет.

Ищу, где я мог ошибиться.
Оказывается, что я не до конца "разглядел" ошибку, что описал в предыдущем сообщении, второго пункта. Догрузка новых уведомлений тут ни при чем, а ссылка "Посмотреть все уведомления", не единственная ссылка, которая не работает. Любая ссылка в блоке не работает, если на ней нет onclick=" ... ". Кроме того, блок уведомлений не один, с кем такая проблема, все три блока имеют такую проблему: Предложения дружбы, Внутренняя почта и Уведомления.

Ну, и сама суть глюка: если сразу после загрузки страницы, в течении ~2,5 секунд, кликнуть на одну из трех ссылок Предложения дружбы, Внутренняя почта или Уведомления, ссылки в них работать не будут.

На данный момент временно решил так: открываю: "theme/full/jscript/main.js" (У меня изменено местонахождение файлов), нахожу:
	$('#holder_notify ul li a').click(function()
	{
		// Avoid the ajax browsing to close the drop-down
		if($(this).attr('rel') == undefined)
		{
			return false;
		}
		
		var $oParent = $(this).parent();
		var $oChild = $oParent.find('.holder_notify_drop');
		
		$('#header_menu_holder ul li ul').removeClass('active');
		$('#header_menu_holder ul li a').removeClass('active');		
		
		if ($oParent.hasClass('is_active'))
		{
			$oParent.removeClass('is_active');
			$oChild.hide();
		}
		else
		{
			$('#holder_notify ul li').removeClass('is_active');
			$('#holder_notify ul li').find('.holder_notify_drop').hide();
			
			$oParent.addClass('is_active');
			$oChild.show();
			/*
			if ($oChild.find('.holder_notify_drop_data').find('.holder_notify_drop_loader').length > 0)
			{
			*/
				$Core.ajax($(this).attr('rel'), 
				{
					params: 
					{					
						'no_page_update': true	
					},
					success: function($sData)			
					{
						$oChild.find('.holder_notify_drop_data').html($sData);
                        if (oCore['core.site_wide_ajax_browsing'])
                        {
                            $Core.loadInit();
                        }
					}
				});
			/*
			}
			else
			{
				if ($(this).attr('rel') == 'mail.getLatest')
				{
					if (isset($aMailOldHistory))
					{
						for ($iKey in $aMailOldHistory)
						{
							$('#js_mail_read_' + $iKey).find('a:first').removeClass('is_new');
						}
					}
				}
				else if ($(this).attr('rel') == 'notification.getAll')
				{
					if (isset($aNotificationOldHistory))
					{
						for ($iKey in $aNotificationOldHistory)
						{
							$('#js_notification_read_' + $iKey).find('a:first').removeClass('is_new');
						}
					}					
				}
			}
			*/
		}
		
		return false;
	});

И меня на:
	// Открытие блока: Заявки в друзья | Внутренняя почта | Уведомления
	$('#holder_notify ul li a').click(function() {
		if ($(this).attr('rel') == undefined) {
			return false;
		};

		var when = Math.round(performance.now());
		if (when < 2500) {
			when = 2500 - when;
		}
		else {
			when = 2500 - when;
		};

		setTimeout(() => {
			var $parent = $(this).parent();
			var $child  = $parent.find('.holder_notify_drop');

			$('#header_menu_holder ul li ul').removeClass('active');
			$('#header_menu_holder ul li a').removeClass('active');

			if ($parent.hasClass('is_active')) {
				$parent.removeClass('is_active');
				$child.hide();
			}
			else {
				$('#holder_notify ul li').removeClass('is_active');
				$('#holder_notify ul li').find('.holder_notify_drop').hide();

				$parent.addClass('is_active');
				$child.show();

				$Core.ajax($(this).attr('rel'), {
					params: {					
						'no_page_update': true	
					},
					success: function($data) {
						$child.find('.holder_notify_drop_data').html($data);
					}
				});
			};
		}, when);

		return false;
	}); // Открытие блока: Заявки в друзья | Внутренняя почта | Уведомления End

Тут я после клика на одну из трех кнопок, проверяю сколько прошло времени с момента загрузки страницы (Тема: Как получить время прошедшее с момента загрузки страницы), если меньше, чем 2,5 секунды, то сценарий дождется, когда с момента загрузки пройдет 2,5 секунды, затем выведет блок. Если страница была загружена более, чем 2,5 секунды назад, то сценарий выводит нужный блок тут же.

Думается мне, что проблема связана с тем, что клик происходит раньше, чем все файлы были загружены, поэтому в планах попробовать вариант из темы: Тема: Можно ли выполнять сценарий только после полной загрузки страницы?.
Чуток поправил код вывода блока, добавил мигание значка, пока блок не отобразится (Тема: Эффект мигания). Сейчас код выглядит так:
	// Открытие блока: Заявки в друзья | Внутренняя почта | Уведомления
	$('#holder_notify ul li a').click(function() {
		if ($(this).attr('rel') == undefined) {
			return false;
		};

		var icoPathNotify = $(this).find('.icoPathNotify');

		var twinkl = setInterval(() => {
			if (icoPathNotify.css('fill') == 'rgb(255, 255, 255)') {
				icoPathNotify.css('fill', '#999999');
			}
			else {
				icoPathNotify.css('fill', '#FFFFFF');
			};
		}, 300);

		var when = Math.round(performance.now());
		if (when < 2500) {
			when = 2500 - when;
		}
		else {
			when = 2500 - when;
		};

		setTimeout(() => {
			var $parent = $(this).parent();
			var $child  = $parent.find('.holder_notify_drop');

			$('#header_menu_holder ul li ul').removeClass('active');
			$('#header_menu_holder ul li a').removeClass('active');

			if ($parent.hasClass('is_active')) {
				$parent.removeClass('is_active');
				$child.hide();
			}
			else {
				$('#holder_notify ul li').removeClass('is_active');
				$('#holder_notify ul li').find('.holder_notify_drop').hide();

				$parent.addClass('is_active');
				$child.show();

				$Core.ajax($(this).attr('rel'), {
					params: {					
						'no_page_update': true	
					},
					success: function($data) {
						$child.find('.holder_notify_drop_data').html($data);
					}
				});
			};

			clearInterval(twinkl);
			icoPathNotify.css('fill', '#FFFFFF');
		}, when);

		return false;
	}); // Открытие блока: Заявки в друзья | Внутренняя почта | Уведомления End

Поработал с правами доступа к страницам/группам. Теперь блоки "Последние статьи" и "Последние затронутые темы" унаследуют права группы. Если пользователю запрещено читать форум или блог, то и блоков с ссыками на темы и статьи он не увидит.
Повозился с обработкой URL. Теперь, если в URL будут лишние слеши (/), они будут удалены (Тема: Удаление лишних слешев в URL).

Заметил, что при переходе к номеру страницы, которая не существует, например, текущая тема: forum/thread/643/page_999999999999999999999/. Такой страницы: 999999999999999999999 у этой темы нет, на данный момент страниц всего три. Но, сценарий обработает, будто есть и выведет сообщения с третей страницы. На мой взгляд это неправильно. Решил так: В библиотеку pager, в метод set, вставил следующее:
		// Перенаправление на последнюю страницу (На случай перехода на несуществующий номер страницы)
		if ($this->pagesCount < $params['page'])
		{
			$url = preg_replace('/page_(\d+)/', 'page_' . $this->pagesCount, $this->_aParams['do']);

			phpfox::getLib('url')->send($url, [], null, 301);
		} // Перенаправление на последнюю страницу (На случай перехода на несуществующий номер страницы) End

Не уверен, что эта библиотека подходит для этой проверки, возможно, в будущем перенесу код в другой файл. Но, пока все отлично работает.
После добавления кода, что в предыдущем сообщении, в фотоальбоме появились проблемы (Тема: Почему после сравнения меняется значение переменных?), из за чего пришлось пересматривать сравнение текущей и последней страницы. Сейчас делаю непосредственно в самом файле контролера. Код для всех контролеров +/- одинаковый:
		// Пагинация
		define('PHPFOX_PAGER_FORCE_COUNT', true);

		$pager = phpfox::getLib('pager');
	
		$pager->set([
			    'page'  => $pageID,
				'size'  => $pageIDSize,
				'count' => $cnt
			]
		);

		if ($pageID > $pager->getTotalPages())
		{
			$this->url()->send('error.404');
		} // Пагинация End

Если контролер использует: $this->search()->browse()->params($browseParams)->execute();, то перенаправление на 404 страницу не нужно:
		if ($pageID > $pager->getTotalPages())
		{
			$this->url()->send('error.404');
		}

Так как библиотека phpfox_search_browse уже проверяет текущею страницу с общим количеством страниц и в случае перебора, перекидывает на 404 страницу.
При добавлении новой настройки, описание опции добавляется только для английского языка. Исправил это в классе Admincp_Service_Setting_Process, исправив часть кода так:
		$langIDs = [];
		$langs = phpfox::getService('language')->get();
		foreach ($langs as $lang)
		{
			$langIDs[$lang['language_id']] = '<title>' . $vals['title'] . '</title><info>' . $vals['info'] . '</info>';
		}

		$phrase = phpfox::getService('language.phrase.process')->add([
				'var_name'   => 'setting_' . $vals['var_name'],
				'product_id' => $productID,
				'module'     => (empty($module) ? 'core|core' : $module . '|' . $module),
				'text'       => $langIDs
			]
		);

Более разумный вариант: Тема: Как при добавлении опций создавать переменные для всех языков.

Исправил отображение списка лайкнувших (В блоке). Раньше отображались все пользователи, сразу. Сейчас список догружается при прокрутки вниз.
Поработал со своим давнем расширением "Возрастное ограничение". Ранее появлялось предупреждение о том, что контент могут смотреть только лица достигшие восемнадцатилетия, на главной странице (Модуль "pages"), то есть на новостной ленте какой ли бо группе, у которой наложено возрастное ограничение. Однако, по отдельности, каналы смотреть без предупреждения можно было, то есть, видео, фото, статьи, опросы и темы форума страницы для взрослых смотреть без предупреждения можно было. Я это исправил, теперь предупреждение появляется на всех связанных страницах с группой для взрослых.

Пример: Код для фотоальбома, в файле: "module/photo/include/component/controller/album.class.php"
		if ($album['module_id'] == 'pages')
		{
			$pageData = phpfox::getService('pages')->getPage($album['group_id']);

			// Проверка возраста ограничения
			if ($pageData['limitation'] && $limitation = phpfox::getService('user')->limitation())
			{
				$this->template()->assign([
						'limitation' => $limitation
					]
				);
			} // End: Проверка возраста ограничения
		}
Установил PHP 8.2.0. Теперь провожу работу по обновлению кода движка.

Удалил модуль "Эмоции", за ненадобностью.
Уже пару дней работаю над микроразметкой формата JSON-LD (Тема: Микроразметка сайта для поисковых систем (Формат JSON-LD)). На данный момент разметка есть не на всех страницах.

Размечены объекты:
- Хлебные крошки.
- Видео.
- Статьи.

Для этого написал библиотеку seo.json-ld, которая генерирует и выводит в исходный код микроразметку.

Продолжаю работу с микроразметкой.
Поработал с блоком "Категории блога". Теперь в блоге профиля пользователя блог выводит заголовки страниц, в которых была добавлена категория, и в нее были добавлены статьи.



Работа на блоком категорий продолжается.
Переделал блок категорий (Тегов) для блога, сделал возможность добавления категории для записи: блога, форума, фото, видео и опроса, и все это обрабатывает один и тот же сценарий. От "родных" блоков "Категории" я отказываюсь, и в планах у меня вырезать их окончательно. Мне очень понравился вариант, где пользователи сами могут создавать и назначать категории своим записям.
Заметил, что при включенном отладчике (Проверял на тройке), при загрузки фотографии, в ленту новостей, сценарий полностью не отрабатывает. В консоли браузера появляется: Uncaught SyntaxError: Unexpected token '<'. В лог залетает ошибка: a client request body is buffered to a temporary. Пробовал менять значение client_body_buffer_size, но, ни чего не изменилось.

Проблему пытаюсь решить.
Исправил ошибку, описанную в предыдущем сообщении. В моем случае, всему виной был кусок кода, из файла: "module/photo/include/component/controller/frame.class.php":
				if ($isInline && phpfox::isModule('video') && phpfox::getParam('video.convert_servers_enable'))
				{
					echo 'document.domain = "' . phpfox::getParam('video.convert_js_parent') . '";';
				}

Дело в том, что я вырезаю возможность загрузки видеофайлов на сервер, стер параметры video.convert_servers_enable и video.convert_js_parent из БД, и как оказалось, удалил остатки сценария загрузки, не до конца. Я удалил данный кусок кода и загрузка фотографий, при включенном отладчике работает безупречно. Консоль браузера тоже чиста.
Написал инструмент для переноса предметов (Фото, Видео, Статей, Опросов) из одной страницы (Модуль "pages") на другую. Инструмент расположил в Админ разделе и доступен только мне. На данный момент работа над разработкой продолжается, однако, основной функционал полностью готов и уже протестирован. Для переноса, достаточно вставить URL предмета и URL страницу, куда будет перемещен предмет. Если автор предмета является сообщество, то автор будет изменен на автора нового сообщества. Автор остается без изменения, если предмет был добавлен пользователем, а не сообществом.

На данный момент перенести можно:
  1. Статьи блога.
  2. Темы форума.
  3. Опрос.
  4. Фотографию.
  5. Видео.

Планирую дополнить список предметов для переноса. А так же добавить возможность переносить все предметы страницы на другую страницу, массово.
В теме: Удаление записей большого объёма в MySQL (Удаление записей большого объёма в MySQL (Сообщение: 6510)) я рассказал, как можно сделать удаление записей большого объема, при помощи временных записей в отдельной таблице. И по такому принципу я начал делать обработку данных движка, например, очистка мусора, пересчет количества предметов (комменты, лайки, фото, блоги и так далее).

Раньше, при пересчете, например, фотографий пользователей, необходимо было ждать, когда сценарий пройдет все этапы обработки, перезагружая страницу, каждые две секунды. Теперь все происходит в "фоновом режиме". Ждать окончания операции не нужно.
Пересмотрел свою доработку категорий и вырезал их из профилей пользователя, теперь они есть только в модуле "pages". Так же, они для блога, форума, фото, опросника и видео. Так же, создавать и удалять категории может только администратор страницы, а выбирать подходящею категорию, для своей записи, может кто угодно. Если запись имеет категорию, тег будет отображен в списке записей, например, форум, выглядит так:

Журнал пользователя движка phpFOX 3

Заменил скучные checkbox'ы для выбора категории, на более приятные кнопки:

Журнал пользователя движка phpFOX 3

URL категорий тоже изменил, ранее он был: phpfox/forum/category/15/, теперь: phpfox/forum/category_15/. Такое решение помогло исправить сразу несколько костылей, и сократить код.

Еще было сделано:
- Как планировал (Тема: Журнал пользователя движка phpFOX 3 (Сообщение отдельно: 6529)), расширил список предметов, которых можно переносить. А так же, теперь можно переносить страницу полностью. Для этого необходимо указать адрес страницы, которую надо перенести, и адрес страницы, куда будут перемещены все записи страницы.

- Запретил использовать слова mobile и full, в URL страницы (Модуль "pages"). Это зарезервированные слова, что служат для перехода в мобильную версию сайта и на версию для ПК.

- Убрал кнопку "Добавить запись" (Для блога, форума, фото и так далее), в мобильной версии, если админ страницы запрещает создавать новые записи. В полной версии это было сделано изначально, а вот мобильная версия игнорировала настройки прав доступа.

- Исправил глюк с URL главной страницы опросов. Ранее, если страница (Модуль: "pages") не имеет vanity_url, то есть URL такой: site/pages/70/, а не site/phpfox/, то главная страница опроса перенаправляла на страницу опроса, что poll_id совпадает с page_id. Теперь этой проблемы нет.
Продолжаю работать над "плавной обработкой данных" (Я так назвал) (Тема: Журнал пользователя движка phpFOX 3 (Сообщение отдельно: 6557)). На этот раз я исправил удаление страниц и пользователей. У сообщества, что надо удалить, может быть громадное количество записей, если удалить все разом, то можно получить ошибку 500, при которой может остаться мусор. Я, так же, разделил удаление записей на этапы. На скорость сайта, удаление не влияет.

С удалением пользователя то же самое, его записи удаляются по 150 штук в минуту, затем удаляется сам пользователь.
Работа с категориями не останавливается! Я изменил вид тегов, убрал разноцветные цвета, сделал все одинаково серого цвета. Как мне кажется, так выглядит солиднее и красивее, чем разноцветные кнопки.

Журнал пользователя движка phpFOX 3

Заодно поправил вид списка тем, в форуме.

Убрал лишние папки в модулях, в которых находились файлы стиля.
Раньше было так: "css/default/default/file.css".
Теперь так: "css/file.css".
Как по мне, так лучше.
Повозился с комментариями. Вернул аватарки. На ответах к комментам, аватарки меньше. Если отвечать на ответ комментария (Хм...), то ответ будет иметь пометку, что является ответом на ответ. Наведя на метку [Ответ] появится окошко с полным содержимым, на что был дан ответ.

Журнал пользователя движка phpFOX 3