<?php
declare(strict_types = 1);

require_once(__DIR__ . '/Gallery.class.php');

/**
 * Opérations concernant les fichiers.
 *
 * @license https://www.gnu.org/licenses/gpl-3.0.html
 * @link https://www.igalerie.org/
 */
class GalleryItems extends Gallery
{
	/**
	 * Informations en base de données du fichier courant.
	 *
	 * @var array
	 */
	public static $infos = [];



	/**
	 * Récupération des fichiers de l'album courant.
	 *
	 * @return int
	 */
	public static function getAlbumItems(): int
	{
		self::_pagination(1);

		// Nombre de fichiers par page.
		$items_per_page = (int) Config::$params['thumbs_item_nb_per_page'];
		$items_per_page = $items_per_page < 1 ? 1000000 : $items_per_page;
		Template::set('items_per_page', $items_per_page);

		// Récupération des informations des fichiers.
		if (is_int($items = self::_getItems($items_per_page)))
		{
			return $items;
		}

		self::_pagination(ceil(Template::$data['objects_count'] / $items_per_page));

		// Formatage des informations.
		$formated_infos = [];
		foreach ($items as &$i)
		{
			$formated_infos[] = self::getFormatedInfos($i, 'thumb');
		}
		Template::set('items', $formated_infos);

		return 1;
	}

	/**
	 * Formate les informations d'un fichier.
	 *
	 * @param array $i
	 *   Informations brutes du fichier.
	 * @param string $origin
	 *   Origine : 'item' ou 'thumb'.
	 *
	 * @return array
	 */
	public static function getFormatedInfos(array &$i, string $origin = 'item'): array
	{
		$stats =
		[
			'comments' => [],
			'favorites' => [],
			'filesize' => [],
			'rating' => [],
			'views' => [],
			'votes' => []
		];

		$comments = function() use (&$i)
		{
			if (Config::$params['comments'])
			{
				if (Config::$params['users'] && !Auth::$groupPerms['comments_read'])
				{
					return
					[
						'short' => L10N::formatShortNumber(0),
						'text' => sprintf(__('%s commentaire'), L10N::formatNumber(0)),
						'value' => 0
					];
				}
				return
				[
					'short' => L10N::formatShortNumber((int) $i['item_comments']),
					'text' => sprintf(
						$i['item_comments'] > 1 ? __('%s commentaires') : __('%s commentaire'),
						L10N::formatNumber((int) $i['item_comments'])
					),
					'value' => (int) $i['item_comments']
				];
			}
		};

		$date = function() use (&$i)
		{
			$text = L10N::dt(__('%d/%m/%Y'), $i['item_pubdt']);
			return
			[
				'short' => $text,
				'text' => $text,
				'value' => $i['item_pubdt']
			];
		};

		$favorites = function() use (&$i)
		{
			if (Config::$params['users'] && Config::$params['favorites'])
			{
				return
				[
					'short' => L10N::formatShortNumber((int) $i['item_favorites']),
					'text' => sprintf(
						$i['item_favorites'] > 1 ? __('%s favoris') : __('%s favori'),
						L10N::formatNumber((int) $i['item_favorites'])
					),
					'value' => (int) $i['item_favorites']
				];
			}
		};

		$filesize = function() use (&$i)
		{
			return
			[
				'text' => $i['item_filesize']
					? L10N::formatFilesize($i['item_filesize'])
					: 0,
				'value' => (int) $i['item_filesize']
			];
		};

		$rating = function() use (&$i)
		{
			if (Config::$params['votes'])
			{
				return
				[
					'array' => Rating::formatArray($i['item_rating']),
					'formated' => L10N::formatRating($i['item_rating']),
					'value' => (float) $i['item_rating']
				];
			}
		};

		$views = function() use (&$i)
		{
			return
			[
				'short' => L10N::formatShortNumber((int) $i['item_hits']),
				'text' => sprintf(
					$i['item_hits'] > 1 ? __('%s vues') : __('%s vue'),
					L10N::formatNumber((int) $i['item_hits'])
				),
				'value' => (int) $i['item_hits']
			];
		};

		$votes = function() use (&$i)
		{
			if (Config::$params['votes'])
			{
				return
				[
					'short' => L10N::formatShortNumber((int) $i['item_votes']),
					'text' => sprintf(
						$i['item_votes'] > 1 ? __('%s votes') : __('%s vote'),
						L10N::formatNumber((int) $i['item_votes'])
					),
					'value' => (int) $i['item_votes']
				];
			}
		};

		foreach ($stats as $name => $data)
		{
			if ($origin == 'item' || Config::$params['thumbs_item_info_' . $name])
			{
				if ($r = ${$name}())
				{
					$stats[$name] = $r;
				}
			}
		}

		$date_created = $origin == 'item';
		$date_published = $origin == 'item' || Config::$params['thumbs_item_info_date'];
		$size = $origin == 'item' || Config::$params['thumbs_item_info_size'];

		// Orientation.
		if ($size && in_array($i['item_orientation'], [5, 6, 7, 8]))
		{
			$width = $i['item_width'];
			$i['item_width'] = $i['item_height'];
			$i['item_height'] = $width;
		}

		// Coordonnées de géolocalisation.
		$coords = $i['item_lat'] && $i['item_long']
			? Geolocation::getSexagesimalCoordinates($i['item_lat'], $i['item_long'])
			: '';

		// Informations de vignettes pour les filtres.
		$stats['filter'] = [];
		if ($origin == 'thumb' && isset($_GET['filter'])
		&& (in_array($_GET['filter'], ['comments', 'favorites', 'votes', 'views'])
		|| substr($_GET['filter'], 0, 6) == 'recent'))
		{
			if (substr($_GET['filter'], 0, 6) == 'recent')
			{
				$stats['filter'] = $date();
				$date_published = FALSE;
			}
			else
			{
				$stats['filter'] = ${$_GET['filter']}();
			}
			if ($_GET['filter'] == 'votes')
			{
				$stats['rating'] = $rating();
			}
		}

		// Recherche avancée.
		if (Config::$params['search_advanced'] && is_object(self::$search))
		{
			if (!empty(self::$search->options['date']))
			{
				switch (self::$search->options['date_column'])
				{
					case 'item_crtdt' :
						$date_created = TRUE;
						break;
					case 'item_pubdt' :
						$date_published = TRUE;
						break;
				}
			}
			if (!empty(self::$search->options['item_size']))
			{
				$size = TRUE;
			}
			if (!empty(self::$search->options['item_filesize']))
			{
				$stats['filesize'] = $filesize();
			}
		}

		return
		[
			'filename' => basename($i['item_path']),
			'id' => $i['item_id'],
			'url' => $i['item_url'],

			// Sources et liens.
			'link' => self::getURLFilter('item/' . $i['item_id'] . '-' . $i['item_url'], TRUE),
			'link_admin' => App::getURLAdmin('item-edit/' . $i['item_id']),
			'link_item' => App::getURL('item/' . $i['item_id'] . '-' . $i['item_url']),
			'source' => App::getImageResize($i),
			'source_download' => !empty(Template::$data['item_download'])
				? App::getFileSource($i['item_path'], TRUE)
				: '',

			// Type.
			'is_image' => Item::isImage($i['item_type']),
			'is_video' => Item::isVideo($i['item_type']),
			'type' => $i['item_type'],
			'type_mime' => Item::getTypeMime($i['item_type']),
			'type_text' => Item::getTypeText($i['item_type']),

			// Dates.
			'date_created' => $date_created
				? substr((string) $i['item_crtdt'], 0, 10)
				: '',
			'date_created_link' => $origin == 'item'
				? App::getURL('category/1/date-created/'
					. substr((string) $i['item_crtdt'], 0, 10))
				: '',
			'date_created_short' => $date_created
				? ($i['item_crtdt'] ? L10N::dt(__('%d/%m/%Y'), $i['item_crtdt']) : '')
				: '',
			'date_created_text' => $origin == 'item'
				? ($i['item_crtdt'] ? L10N::dt(__('%A %d %B %Y'), $i['item_crtdt'], FALSE) : '')
				: '',
			'datetime_created' => $date_created
				? $i['item_crtdt']
				: '',
			'datetime_created_text' => $origin == 'item'
				? ($i['item_crtdt']
					? L10N::dt(__('%A %d %B %Y à %H:%M:%S'), $i['item_crtdt'], FALSE)
					: '')
				: '',
			'date_published' => $date_published
				? substr((string) $i['item_pubdt'], 0, 10)
				: '',
			'date_published_link' => $origin == 'item'
				? App::getURL('category/1/date-published/'
					. substr((string) $i['item_pubdt'], 0, 10))
				: '',
			'date_published_short' => $date_published
				? L10N::dt(__('%d/%m/%Y'), $i['item_pubdt'])
				: '',
			'date_published_text' => $origin == 'item'
				? L10N::dt(__('%A %d %B %Y'), $i['item_pubdt'])
				: '',
			'datetime_published' => $date_published
				? $i['item_pubdt']
				: '',
			'datetime_published_text' => $origin == 'item'
				? L10N::dt(__('%A %d %B %Y à %H:%M:%S'), $i['item_pubdt'])
				: '',
			'is_recent' => Config::$params['items_recent']
				&& strtotime($i['item_pubdt']) > Item::getRecentTimestamp(),

			// Sélection.
			'in_selection' => (int) !empty($i['in_selection']),

			// Paramètres de l'utilisateur connecté.
			'user' =>
			[
				// Permission d'éditer le fichier ?
				'edit' => Auth::$isAdmin || (Config::$params['users']
					&& Auth::$id != 2 && $i['user_id'] == Auth::$id),

				// Dans les favoris ?
				'in_favorites' => (int) !empty($i['in_favorites']),

				// Note.
				'rating' => $i['rating'] ?? NULL,
				'rating_array' => Rating::formatArray($i['rating'] ?? 0),
				'rating_formated' => L10N::formatRating($i['rating'] ?? 0)
			],

			// Utilisateur qui a ajouté le fichier.
			'owner' =>
			[
				'avatar_source' => Avatar::getURL((int) $i['user_id'], (bool) $i['user_avatar']),
				'id' => $i['user_id'],
				'link' => $i['user_id'] == 2 || $i['user_status'] != 1
					|| empty(Auth::$groupPerms['members_profile'])
					? NULL
					: App::getURL('user/' . $i['user_id']),
				'nickname' => $i['user_id'] == 2
					? '/'
					: User::getNickname($i['user_login'], $i['user_nickname'])
			],

			// Métadonnées.
			'exif' => $i['exif'] ?? [],
			'iptc' => $i['iptc'] ?? [],
			'xmp' => $i['xmp'] ?? [],

			// Tags.
			'tags' => $i['tags'] ?? [],
			'tags_list' => $i['tags_list'] ?? [],

			// Géolocalisation.
			'geolocation_coords' => $coords
				? sprintf('%s, %s', $coords['latitude'], $coords['longitude'])
				: '',
			'geolocation_lat' => $i['item_lat'],
			'geolocation_long' => $i['item_long'],

			// Dimensions.
			'width' => $size ? $i['item_width'] : '',
			'height' => $size ? $i['item_height'] : '',

			// Durée.
			'duration' => $i['item_duration'],
			'duration_text' => $i['item_duration']
				? App::formatDuration($i['item_duration'])
				: '00:00',

			// Informations.
			'description' => $i['item_desc'],
			'title' => ($origin == 'item' || Config::$params['thumbs_item_info_title'])
				? $i['item_name']
				: '',

			// Statistiques.
			'stats' => $stats,

			// Vignette.
			'thumb_size' => function(int $max_width, int $max_height) use (&$i): array
			{
				if (!$i['item_width'] || !$i['item_height'])
				{
					$i['item_width'] = 400;
					$i['item_height'] = 227;
				}
				return Image::getResizedSize((int) $i['item_width'],
					(int) $i['item_height'], $max_width, $max_height);
			},
			'thumb_src' => function($size = '', $quality = '', $poster = FALSE) use (&$i): string
			{
				return htmlspecialchars(
					App::getThumbSource(
						'item', $i, (string) $size, (string) $quality, (bool) $poster
					)
				);
			}
		];
	}

	/**
	 * Récupération des informations du fichier courant.
	 *
	 * @return int
	 */
	public static function getInfos(): int
	{
		$params = ['item_id' => $_GET['item_id']];
		$sql_favorites = '0';
		if (Config::$params['users'] && Auth::$connected)
		{
			$sql_rating = 'SELECT vote_rating
							 FROM {votes}
							WHERE item_id = i.item_id
							  AND user_id = :user_id
							LIMIT 1';
			if (Config::$params['favorites'])
			{
				$sql_favorites = 'SELECT 1
									FROM {favorites}
								   WHERE item_id = i.item_id
									 AND user_id = :user_id
								   LIMIT 1';
			}
			$params['user_id'] = Auth::$id;
		}
		else
		{
			$sql_rating = 'SELECT vote_rating
							 FROM {votes}
							WHERE item_id = i.item_id
 							  AND user_id = 2
							  AND vote_cookie = :vote_cookie
							LIMIT 1';
			$params['vote_cookie'] = Auth::$prefs->read('rating');
		}
		$sql = "SELECT i.*,
					   cat.*,
					   " . SQL::catPassword('select') . ",
					   'album' AS cat_type,
					   u.user_id,
					   u.user_avatar,
					   u.user_login,
					   u.user_nickname,
					   u.user_status,
					   cam_m.*,
					   cam_b.*,
					   ($sql_rating) AS rating,
					   ($sql_favorites) AS in_favorites,
					   (" . Selection::getSQLItem() . ") AS in_selection
				  FROM {items} AS i
		     LEFT JOIN {categories} AS cat
				    ON i.cat_id = cat.cat_id
		     LEFT JOIN {users} AS u
				    ON i.user_id = u.user_id
		     LEFT JOIN {cameras_items} AS cam_i
				    ON cam_i.item_id = i.item_id
		     LEFT JOIN {cameras_models} AS cam_m
				    ON cam_m.camera_model_id = cam_i.camera_model_id
		     LEFT JOIN {cameras_brands} AS cam_b
				    ON cam_b.camera_brand_id = cam_m.camera_brand_id
			     WHERE item_status = '1'
				   AND i.item_id = :item_id
				   AND " . SQL::catPerms();
		DB::params($params);
		if (!DB::execute($sql))
		{
			return -1;
		}
		if (!isset((self::$infos = DB::fetchRow())['item_id']))
		{
			return 0;
		}

		// L'utilisateur a-t-il entré le bon mot de passe ?
		if (!self::checkCookiePassword(self::$infos))
		{
			return 0;
		}

		// Fil d'Ariane.
		Template::breadcrumb(self::$infos, TRUE);

		// Réglages.
		self::$infos['cat_parents'] .= self::$infos['cat_id'] . Parents::SEPARATOR;
		self::$infos = [self::$infos];
		Parents::settings(self::$infos);
		self::$infos = self::$infos[0];

		// Métadonnées
		$metadata = self::getMetadata(self::$infos);
		foreach (['exif', 'iptc', 'xmp'] as $meta)
		{
			self::$infos[$meta] = &$metadata[$meta];
		}

		// Tags.
		if (Config::$params['tags'])
		{
			$tags = self::getTags((int) self::$infos['item_id']);
			self::$infos['tags'] = $tags;
			$tags_list = [];
			foreach ($tags as &$i)
			{
				$tags_list[] = $i['name'];
			}
			self::$infos['tags_list'] = $tags_list;
		}

		// Géolocalisation.
		if (Config::$params['geolocation'])
		{
			Template::set('geolocation_default_layer',
				Config::$params['geolocation_default_layer']);
			Template::set('geolocation_default_zoom',
				Config::$params['geolocation_default_zoom']);
			if (self::$infos['item_lat'] === NULL || self::$infos['item_long'] === NULL)
			{
				Template::set('geolocation', 0);
			}
		}

		// Émojis.
		Template::set('comments_emoji_picker', (int) Config::$params['comments_emoji_picker']);

		// Nombre de vues.
		if (Item::hit((int) $_GET['item_id']) > 0)
		{
			self::$infos['item_hits']++;
		}

		// Téléchargement.
		Template::set('item_download', (int) self::itemDownload(self::$infos));

		// Commentaires.
		Template::set('commentable', self::$infos['commentable']
			= (int) (self::$infos['parent_commentable'] && self::$infos['item_commentable']));
		Template::set('comments', (int) Config::$params['comments']);
		Template::set('comments_edit', []);

		// Votes.
		Template::set('votable', self::$infos['votable']
			= (int) (self::$infos['parent_votable'] && self::$infos['item_votable']));
		Template::set('votes', (int) Config::$params['votes']);
		Template::set('votes_add', (int) (!Config::$params['users']
			|| (Config::$params['users'] && Auth::$groupPerms['votes'])));

		// Permission d'édition pour les administrateurs
		// et le propriétaire du fichier.
		Template::set('item_edit', (int) (Auth::$isAdmin
			|| (Config::$params['users'] && self::$infos['user_id'] == Auth::$id)));

		// Formatage des informations.
		Template::set('item', self::getFormatedInfos(self::$infos, 'item'));
		Template::set('category', GalleryCategory::getFormatedInfos(self::$infos));

		// URL canonique.
		Template::set('canonical', GALLERY_HOST . App::getURL('item/'
			. self::$infos['item_id'] . '-' . self::$infos['item_url']));

		// Description.
		Template::$data['item']['description_edit'] = Template::$data['item']['description'];

		// Description pour balise <meta>.
		Template::set('meta_description',
			App::getMetaDescription((string) self::$infos['item_desc']));

		// Pagination.
		if (is_int($r = self::_itemPagination(self::$infos)))
		{
			return $r;
		}

		// Flux RSS.
		if (Config::$params['rss']
		&& Config::$params['comments'] && self::$infos['commentable'])
		{
			self::_rss('item', self::$infos);
		}

		return 1;
	}

	/**
	 * Retourne les informations EXIF, IPTC et/ou XMP d'un fichier.
	 *
	 * @param array $item_infos
	 *   Informations du fichier.
	 *
	 * @return array
	 */
	public static function getMetadata(array &$item_infos): array
	{
		if (Config::$params['exif'] || Config::$params['iptc'] || Config::$params['xmp'])
		{
			$filename = CONF_ALBUMS_PATH . '/' . $item_infos['item_path'];
			if (Utility::isJson($item_infos['item_exif'])
			 || Utility::isJson($item_infos['item_iptc'])
			 || Utility::isJson($item_infos['item_xmp']))
			{
				$data = [];
				if (Config::$params['exif'])
				{
					$data['exif'] = Utility::jsonDecode($item_infos['item_exif']);
				}
				if (Config::$params['iptc'])
				{
					$data['iptc'] = Utility::jsonDecode($item_infos['item_iptc']);
				}
				if (Config::$params['xmp'])
				{
					$data['xmp'] = Utility::jsonDecode($item_infos['item_xmp']);
				}
				$metadata = new Metadata($filename, $data);
			}
			else if (in_array($item_infos['item_type'], [Item::TYPE_JPEG, Item::TYPE_WEBP])
			&& file_exists($filename))
			{
				$metadata = new Metadata($filename);
			}
		}

		if (isset($metadata))
		{
			if (Config::$params['exif'])
			{
				$exif = $metadata->getExifFormated(Config::$params['exif_params']);
				$exif = Metadata::getSorted($exif, Config::$params['exif_order']);
				foreach ($exif as $p => &$i)
				{
					if ($p == 'Make')
					{
						$i['link'] = App::getURL(
							'category/1/camera-brand/'
							. $item_infos['camera_brand_id'] . '-'
							. $item_infos['camera_brand_url']
						);
					}
					if ($p == 'Model')
					{
						$i['link'] = App::getURL(
							'category/1/camera-model/'
							. $item_infos['camera_model_id'] . '-'
							. $item_infos['camera_model_url']
						);
					}
				}
			}

			if (Config::$params['iptc'])
			{
				$iptc = $metadata->getIptcFormated(Config::$params['iptc_params']);
				$iptc = Metadata::getSorted($iptc, Config::$params['iptc_order']);
			}

			if (Config::$params['xmp'])
			{
				$xmp = $metadata->getXmpFormated(Config::$params['xmp_params']);
				$xmp = Metadata::getSorted($xmp, Config::$params['xmp_order']);
			}
		}

		return ['exif' => $exif ?? [], 'iptc' => $iptc ?? [], 'xmp' => $xmp ?? []];
	}

	/**
	 * Retourne les tags liés à un fichier.
	 *
	 * @param int $item_id
	 *   Identifiant du fichier.
	 *
	 * @return array
	 */
	public static function getTags(int $item_id): array
	{
		$tags = [];
		if (Config::$params['tags'])
		{
			$sql = "SELECT t.*
					  FROM {tags} AS t,
						   {tags_items} AS ti
					 WHERE t.tag_id = ti.tag_id
					   AND ti.item_id = ?";
			if (DB::execute($sql, $item_id))
			{
				foreach (DB::fetchAll() as &$tag)
				{
					$tags[$tag['tag_name']] =
					[
						'link' => App::getURL(
							'category/1/tag/' . $tag['tag_id'] . '-' . $tag['tag_url']
						),
						'name' => $tag['tag_name']
					];
				}
				uksort($tags, 'Utility::alphaSort');
			}
		}
		return array_values($tags);
	}

	/**
	 * Détermine si un fichier peut être téléchargé
	 * en fonction des permissions sur ce fichier et des
	 * paramètres de configuration.
	 *
	 * @param array $i
	 *   Informations du fichier.
	 *
	 * @return bool
	 */
	public static function itemDownload(array &$i): bool
	{
		return $i['parent_downloadable']
			&& $i['item_downloadable']
			&& Config::$params['download_item'] &&
			 (!Config::$params['users'] ||
			  (Config::$params['users'] && Auth::$groupPerms['image_original']));
	}



	/**
	 * Récupération de fichiers.
	 *
	 * @param int $items_per_page
	 *   Nombre de fichiers par page (section "album").
	 *
	 * @return array|int
	 *   Retourne un tableau des informations des fichiers,
	 *   -1 en cas d'erreur ou 0 si aucun fichier n'a été trouvé.
	 */
	private static function _getItems(int $items_per_page = 0)
	{
		Template::set('objects_count', 0);
		Template::set('objects_count_formated', '0');

		$sql_where = [];
		$params = [];

		// Filtres.
		if (isset($_GET['filter']))
		{
			if (($_GET['filter'] == 'search' && $where = self::$search->sql())
			|| $where = SQL::itemsWhere($_GET['filter'], $_GET['filter_value']))
			{
				if (substr($_GET['filter'], 0, 4) == 'user'
				&& Config::$params['users'] && !Auth::$groupPerms['members_profile'])
				{
					return 0;
				}
				$sql_where[] = $where['sql'];
				$params = $where['params'];
			}
			else if ($_GET['filter'] == 'search')
			{
				return 1;
			}
		}

		// Limitation à la catégorie courante.
		if (isset($_GET['filter']) && $_GET['section'] == 'item')
		{
			if ($_GET['filter_cat_id'] > 1)
			{
				$sql = 'SELECT cat_id AS id,
							   cat_url AS urlname,
							   cat_name AS title,
							   cat_path,
							   CASE WHEN cat_filemtime IS NULL
									THEN "category" ELSE "album"
									 END AS type
						  FROM {categories}
						 WHERE cat_id = ?';
				if (DB::execute($sql, $_GET['filter_cat_id']))
				{
					if (!$category_filter = DB::fetchRow())
					{
						return 0;
					}
					$sql_where[] = 'item_path LIKE :path';
					$params['path'] = DB::likeEscape($category_filter['cat_path']) . '/%';
					unset($category_filter['cat_path']);
					Template::set('category_filter', $category_filter);
				}
			}
		}
		else if (Template::$data['category']['id'] > 1)
		{
			if (isset($_GET['filter']))
			{
				$sql_where[] = 'item_path LIKE :path';
				$params['path'] = DB::likeEscape(Template::$data['category']['path']) . '/%';
			}
			else
			{
				$sql_where[] = 'i.cat_id = :cat_id';
				$params['cat_id'] = (int) Template::$data['category']['id'];
			}
		}

		// Clause ORDER BY.
		$sql_order_by = Config::$params['items_sql_order_by'];
		if (!$filter = $_GET['filter'] ?? '')
		{
			$sql_order_by = self::$infos['cat_orderby']
				?? GalleryCategory::$infos['cat_orderby']
				?? $sql_order_by;
		}
		$sql_order_by = SQL::itemsOrderBy($filter, $sql_order_by, GalleryCategory::$infos);

		// Clause FROM.
		$sql_from = self::_sqlItemsFrom();

		// Clause WHERE.
		$sql_where[] = 'item_status = "1"';
		$sql_where = implode(' AND ', $sql_where);

		// Récupération des fichiers.
		if ($items_per_page)
		{
			$start = $items_per_page * ($_GET['page'] - 1);
			$sql = "SELECT i.*,
						   cat.cat_parents,
						   u.user_avatar,
						   u.user_login,
						   u.user_nickname,
						   u.user_status
					  FROM {items} AS i
						   $sql_from
				 LEFT JOIN {categories} AS cat
						ON i.cat_id = cat.cat_id
				 LEFT JOIN {users} AS u
						ON i.user_id = u.user_id
					 WHERE $sql_where
					   AND %s
					   AND %s
				  ORDER BY $sql_order_by
					 LIMIT $start,$items_per_page";
		}
		else
		{
			$sql = "SELECT i.item_id,
						   i.item_url,
						   i.item_type
					  FROM {items} AS i
						   $sql_from
				 LEFT JOIN {categories} AS cat
						ON i.cat_id = cat.cat_id
					 WHERE $sql_where
					   AND %s
					   AND %s
				  ORDER BY $sql_order_by";
		}
		DB::params($params);
		if (!DB::execute(sprintf($sql, SQL::catPerms(), SQL::catPassword())))
		{
			return -1;
		}
		if (!$items = DB::fetchAll())
		{
			if ($_GET['page'] > 1 && $_GET['section'] != 'item')
			{
				App::redirect($_GET['q_pageless']);
			}
			else if (isset($_GET['filter']) && $_GET['section'] == 'item')
			{
				App::redirect('category/1/' . $_GET['filter']
					. ($_GET['filter_value'] == $_GET['filter_cat_id']
					? '' : '/' . $_GET['filter_value']));
			}
			return (int) (isset($_GET['filter'])
				&& !strstr($_GET['filter'], 'camera')
				&& !strstr($_GET['filter'], 'date')
				&& !strstr($_GET['filter'], 'tag')
				&& !strstr($_GET['filter'], 'user'));
		}

		// Si le fichier courant ne se trouve pas dans la liste
		// des fichiers correspondant au filtre actuel, on redirige
		// vers la page du fichier sans le filtre.
		if ($_GET['section'] == 'item' && isset($_GET['filter'])
		&& array_search(Template::$data['item']['id'], array_column($items, 'item_id')) === FALSE)
		{
			App::redirect($_GET['q_filterless']);
			return 0;
		}

		// Nombre de fichiers.
		if ($items_per_page)
		{
			if (isset($_GET['filter']))
			{
				unset($params['user_id']);
				$sql = "SELECT COUNT(*) AS count,
							   item_type
						  FROM {items} AS i
							   $sql_from
					 LEFT JOIN {categories} AS cat
							ON i.cat_id = cat.cat_id
						 WHERE $sql_where
						   AND " . SQL::catPerms() . "
						   AND " . SQL::catPassword() . "
					  GROUP BY item_type";
				DB::params($params);
				if (DB::execute($sql))
				{
					GalleryCategory::$count = Item::countByTypes(DB::fetchAll('item_type'));
					Template::set('objects_count', (int) GalleryCategory::$count['items']);
				}
			}
			else
			{
				Template::set('objects_count',
					(int) Template::$data['category']['objects_count']);
			}
			Item::userFavorites($items);
			Item::userSelection($items);
		}
		if (isset($_GET['filter']) && $_GET['section'] == 'item')
		{
			GalleryCategory::$count = ['images' => 0, 'items' => count($items), 'videos' => 0];
			foreach ($items as &$i)
			{
				if (in_array($i['item_type'], Item::VIDEO_TYPES))
				{
					GalleryCategory::$count['videos']++;
				}
				else
				{
					GalleryCategory::$count['images']++;
				}
			}
		}

		Template::set('objects_count_formated',
			L10N::formatNumber(Template::$data['objects_count']));

		return $items;
	}

	/**
	 * Informations pour la pagination entre les pages de fichiers.
	 *
	 * @param array $item_infos
	 *
	 * @return mixed
	 */
	private static function _itemPagination(array $item_infos)
	{
		Template::set('pages',
		[
			'count' => 0,
			'first' => ['active' => FALSE, 'link' => ''],
			'prev' => ['active' => FALSE, 'link' => ''],
			'next' => ['active' => FALSE, 'link' => ''],
			'last' => ['active' => FALSE, 'link' => '']
		]);

		// Récupération des informations des fichiers.
		if (is_int($all_items = self::_getItems()))
		{
			return $all_items;
		}

		// Nombre de fichiers.
		$items_count = count($all_items);
		Template::set('objects_count', $items_count);
		Template::set('objects_count_formated', L10N::formatNumber($items_count));

		// Informations de template.
		foreach ($all_items as &$cols)
		{
			unset($cols['item_type']);
			unset($cols['password_auth']);
		}
		$link = function($i) use (&$all_items)
		{
			return isset($all_items[$i])
				? self::getURLFilter('item/' . $all_items[$i]['item_id']
					. '-' . $all_items[$i]['item_url'], TRUE)
				: '';
		};
		for ($i = 0; $i < $items_count; $i++)
		{
			if ($item_infos['item_id'] == $all_items[$i]['item_id'])
			{
				Template::set('pages',
				[
					'count' => (int) $items_count,
					'first' =>
					[
						'active' => $i > 0,
						'link' => $link(0)
					],
					'prev' =>
					[
						'active' => $i > 0,
						'link' => $link($i - 1)
					],
					'next' =>
					[
						'active' => $i + 1 < $items_count,
						'link' => $link($i + 1)
					],
					'last' =>
					[
						'active' => $i + 1 < $items_count,
						'link' => $link($items_count - 1)
					]
				]);
				break;
			}
		}

		// Position du fichier.
		$item_position = array_search(
			[
				'item_id' => self::$infos['item_id'],
				'item_url' => self::$infos['item_url']
			],
			$all_items
		) + 1;
		Template::set('item_position', $item_position);
		Template::set('item_position_formated', L10N::formatNumber($item_position));

		// Page parente pour l'album du fil d'Ariane.
		$items_per_page = (int) Config::$params['thumbs_item_nb_per_page'];
		if ($items_per_page && !isset($_GET['filter']))
		{
			foreach (Template::$data['breadcrumb'] as $k => &$i)
			{
				if ($i['id'] == Template::$data['category']['id'])
				{
					$parent_page = ceil($item_position / $items_per_page);
					if ($parent_page > 1)
					{
						Template::$data['breadcrumb'][$k]['url'] .= '/page/' . $parent_page;
					}
					break;
				}
			}
		}
	}
}
?>