Вложенные файлы в записях (Модуль phpFox: Attachment)

Движок имеет несколько модулей, которые позволяют загружать файлы на сервер, один из таких: Attachment. Данный модуль работает у меня везде, где можно оставить текстовую заметку. Модуль имеет очень большой недостаток - это он не удаляет мусор. То есть изначально модуль имеет функцию, которая удаляет файлы с сервера и записи из БД, но у него не доведена до ума "связь" с другими модулями. Например, я пишу сообщение на форуме и загружаю в свой пост несколько фотографий (через форму загрузки картинок), через какое то время я или модератор удаляет мой пост, сообщение удаляется с форума, а фотографии остаются храниться на сервере, и хранятся они, как мусор, то есть ни где не используются.

Как я понял идею разработчиков: при загрузке вложения, его id должно добавляться в отведенное для этого поле, через запятую (пример: 23,24,25), после отправки записи (например: сообщения на форуме), сценарий получает id добавленного сообщения и изменяет значение поля item_id на id сообщения, всех перечисленных id вложений через запятую, в таблице phpfox_attachment. В таблицу phpfox_forum_post, поле total_attachment записывается количество вложений. При удалении сообщения, проверяется количество вложений (поле: total_attachment), если значение больше ноля, то выполняется сценарий удаления всех вложений, что принадлежат удаляемому сообщению. Для форума выборка для удаления выглядит примерно так:
attachment_id = 238 // ID вложения
user_id = 1 // И используется id пользователя, который имеет право на удаление вложений

Надеюсь понятно объяснил.

Если загружать файл через форму загрузки фала (не картинки), то id будет изменено, но при удалении сообщения с форума, вложение все ровно останется, как на сервере, так и в БД.
Постараюсь исправить этот баг.
Как то писал метод удаления вложений, при проверке их в тексте удаляемой записи.
Код метода:
	// Удаление вложений
	public function deleteAttachment($text, $item = null, $id = null)
	{
		$url = Phpfox::getParam('core.url_attachment');
		if (preg_match('|' . $url . '|isu', $text))
		{
			preg_match_all('|' . $url . '(.*?)\[\/img\]|isu', $text, $matches);
			foreach ($matches[0] as $match)
			{
				$match   = str_replace('[/img]', '', $match);
				$url_arr = explode('attachment/', $match);
				$img     = end($url_arr);

				$img = str_replace('_thumb', '', $img);
				$img = str_replace('_view', '', $img);
				$img = str_replace('.', '%s.', $img);

				$at = $this->database()
				    ->select('attachment_id, user_id')
					->from(Phpfox::getT('attachment'))
					->where('destination = \'' . $img . '\'')
					->execute('getRow');

				if (!empty($at['attachment_id']))
				{
					$this->delete($at['user_id'], $at['attachment_id']);
				}
			}
		}

		if (!empty($item) && !empty($id))
		{
			$atts = $this->database()
				->select('attachment_id, user_id')
				->from(Phpfox::getT('attachment'))
				->where('category_id = \'' . $item . '\' AND item_id = ' . (int) $id)
				->execute('getRows');

			if (!empty($atts))
			{
				foreach ($atts as $at)
				{
					$this->delete($at['user_id'], $at['attachment_id']);
				}
			}
		}
	} // Удаление вложений END

Далее, при удалении, например, сообщения с форума, выполняю код выше, используя (Для все остальных модификаций, делается по аналогии):
Phpfox::getService('attachment.process')->deleteAttachment($post['text'], 'forum', $id);

Тут принцип удаления не продуман. На данный момент, я убираю у себя этот код.
Покопался в коде и нашел, где добавляется тот самый id вложения, попробовал, id для вложенных картинок добавляется и обновляется в БД. Но, есть один косяк. Обо всем по порядку.
Значит, открываем: module/attachment/include/component/controller/frame.class.php, находим:
			echo '
				<script type="text/javascript">
					window.parent.Editor.insert({is_image: true, name: \'\', id: \'' . $iId . ':view\', type: \'image\', path: \'' . $sImagePath . '\'});
				</script>
			';

Меняем на:
			echo '
				<script type="text/javascript">
					var $parent = window.parent.$(\'#' . $this->request()->get('attachment_obj_id') . '\');
					$parent.find(\'.js_attachment:first\').val($parent.find(\'.js_attachment:first\').val() + \'' . $sIds . '\');
					window.parent.Editor.insert({is_image: true, name: \'\', id: \'' . $iId . ':view\', type: \'image\', path: \'' . $sImagePath . '\'});
				</script>
			';

Теперь, id вложенных картинок (через загрузчик фотографий) будут добавляться!

И собственно о косяке, теперь все вложения, не важно загружены они для фотографий или для всех разрешенных файлов, определяются, как вложения загруженные через форму загрузки всех разрешенных файлов и кроме того, что фотография будет вставлена в bbcode [img][/img], так она еще будет подгружаться под постом... Неразумно...

Я уже подумываю об отказе формы загрузки для картинок, все ровно есть форма, которая позволяет загружать любые файлы. Еще вариант: добавить поле в таблицу phpfox_attachment для проверки, через какую форму был загружен файл, но отказ от формы для загрузки фото мне кажется лучшем решением. Еще думаю, стоит рассмотреть вставку фото (через загрузчик фото) в bbcode [attachment][/attachment], а не [img][/img]. В общем, пока думаю, как лучше поступить...
И так, что у меня получилось: я убрал форму загрузки картинок, тут еще подумал - зачем несколько загрузчиков, если есть один для всех файлов. В файле: module/attachment/include/service/process.class.php, дописал метод:
	public function deleteMass($itemId, $categoryId)
	{
		$rows = $this->database()
			->select('attachment_id, user_id')
			->from($this->table)
			->where('item_id = ' . (int) $itemId . ' AND category_id = \'' . $categoryId . '\'')
			->execute('getRows');

		foreach ($rows as $row)
		{
			$this->delete($row['user_id'], $row['attachment_id']);
		}
	}

В файле: module/forum/include/service/post/process.class.php, в метод delete добавил:
		// Удаление вложений
		if ($post['total_attachment'])
		{
			Phpfox::getService('attachment.process')->deleteMass($post['post_id'], 'forum');
		} // Удаление вложений End

Так же добавил (в этом же методе) в первом запросе, на выборку поле total_attachment.

Пример приведен для форума, для остальных модификаций делается по аналогии.
Продолжаю работу. Добавил код для удаления вложений в модуль mail. Письма в данном модуле физически можно удалить только из Админ панели, пользователи могут только переносить в корзину, где будут храниться письма всю оставшиеся жизнь.

В общем, открываю: module/mail/include/service/process.class.php, нахожу функцию adminDelete и добавляю в нее следующий код:
			// Удаление вложений
			if ($mail['total_attachment'])
			{
				Phpfox::getService('attachment.process')->deleteMass($mail['mail_id'], 'mail');
			} // Удаление вложений End

В этой функции, в запрос добавляю поле total_attachment для выборки.
Весь код моей функции:
	// Delicate function, physically deletes a message from the mail and mail_text tables
	public function adminDelete($id)
	{
		Phpfox::getUserParam('admincp.has_admin_access', true);
		Phpfox::getUserParam('mail.can_read_private_messages', true); // they need to see it in order to delete it
		Phpfox::getUserParam('mail.can_delete_others_messages', true);

		if (Phpfox::getParam('mail.threaded_mail_conversation'))
		{
			$mail = $this->database()
				->select('thread_id')
				->from(Phpfox::getT('mail_thread'))
				->where('thread_id = ' . (int) $id)
				->execute('getSlaveRow');

			if (empty($mail['thread_id']))
			{
				return false;
			}			

			$this->database()->delete(Phpfox::getT('mail_thread'), 'thread_id = ' . (int) $id);
			$this->database()->delete(Phpfox::getT('mail_thread_text'), 'thread_id = ' . (int) $id);
			$this->database()->delete(Phpfox::getT('mail_thread_user'), 'thread_id = ' . (int) $id);
		}
		else
		{
			$mail = $this->database()
				->select('mail_id, viewer_user_id, total_attachment')
				->from(Phpfox::getT('mail'))
				->where('mail_id = ' . (int) $id)
				->execute('getSlaveRow');

			if (empty($mail['mail_id']))
			{
				return false;
			}

			// do some logging before deleting?
			$this->database()->delete($this->table, 'mail_id = ' . (int) $id);
			$this->database()->delete(Phpfox::getT('mail_text'), 'mail_id = ' . (int) $id);

			// Удаление вложений
			if ($mail['total_attachment'])
			{
				Phpfox::getService('attachment.process')->deleteMass($mail['mail_id'], 'mail');
			} // Удаление вложений End
		}		

		return true;
	}