<?php if (!defined('BASEPATH')) exit('No direct script access allowed'); 

/**
 * MaxSite CMS
 * (c) http://max-3000.com/
 * Добавления Илья Земсков <ilya@vizr.ru>
 */

/*
	приоритеты и обновление:
	главная - 1 daily
	страница (не blog) - 0.7 monthly
	запись (blog) - 0.5 weekly
	рубрика - 0.3 weekly
*/

# функция автоподключения плагина
function xml_sitemap_autoload($args = array())
{
	mso_hook_add('edit_category', 'xml_sitemap_custom');
	mso_hook_add('new_category', 'xml_sitemap_custom');
	mso_hook_add('delete_category', 'xml_sitemap_custom');
	mso_hook_add('new_page', 'xml_sitemap_custom');
	mso_hook_add('edit_page', 'xml_sitemap_custom');
}

# функция выполняется при активации (вкл) плагина
function xml_sitemap_activate($args = array())
{	
	mso_create_allow('xml_sitemap_to_hook_edit', t('Админ-доступ к настройкам', 'plugins') . ' «' . t('XML Sitemap') . '»');
	xml_sitemap_custom();
	return $args;
}

# функция выполняется при деинсталяции плагина
function xml_sitemap_uninstall($args = array())
{
	mso_delete_option('plugin_xml_sitemap', 'plugins'); # удалим созданные опции
	mso_remove_allow('xml_sitemap_to_hook_edit'); # удалим созданные разрешения
	return $args;
}

# функция плагина - создание sitemap.xml
function xml_sitemap_custom($args = array())
{
	// Настройки по-умолчанию
	$options = mso_get_option('plugin_xml_sitemap', 'plugins', array());

	if(!isset($options['page_hide'])) $options['page_hide'] = '';
	$options['page_hide'] = mso_explode($options['page_hide']);
	
	if(!isset($options['page_cats_hide'])) $options['page_cats_hide'] = '';
	$options['page_cats_hide'] = mso_explode($options['page_cats_hide']);
	
	if(!isset($options['categories_show'])) $options['categories_show'] = '';
	$options['categories_show'] = mso_explode($options['categories_show']);
	
	if(!isset($options['tags_show'])) $options['tags_show'] = true;
	if(!isset($options['comusers_show'])) $options['comusers_show'] = true;
	if(!isset($options['users_show'])) $options['users_show'] = true;
	
	if(!isset($options['url_protocol'])) $options['url_protocol'] = '';

	$freq_priority = array(
		'home' => array( 'changefreq' => 'daily', 'priority' => '1' ),
		'notblog' => array( 'changefreq' => 'monthly', 'priority' => '0.7' ),
		'blog' => array( 'changefreq' => 'weekly', 'priority' => '0.5' ),
		'category' => array( 'changefreq' => 'weekly', 'priority' => '0.3' ),
		'tag' => array( 'changefreq' => 'weekly', 'priority' => '0.3' ),
		'comuser' => array( 'changefreq' => 'weekly', 'priority' => '0.3' ),
		'user' => array( 'changefreq' => 'weekly', 'priority' => '0.3' ),
	);
	if( isset($options['freq_priority']) && $options['freq_priority'] ) 
	{
		$fp = explode(NR, trim($options['freq_priority']));
		foreach($fp as $ln)
		{
			$params = array_map('trim', explode('|', trim($ln)));
			$freq_priority[$params[0]] = array('changefreq' => $params[1], 'priority' => $params[2]);
		}
	}
	$options['freq_priority'] = $freq_priority;

	if(!isset($options['custom_urls'])) $options['custom_urls'] = '';
	$options['custom_urls'] = array_map('trim', explode(NR, trim($options['custom_urls'])));

	if(!isset($options['sitemap-mode'])) $options['sitemap-mode'] = 'simple';
	if(!isset($options['sitemap-index-links']) or $options['sitemap-index-links'] == '') $options['sitemap-index-links'] = 1000;
	if($options['sitemap-index-links'] > 50000 ) $options['sitemap-index-links'] = 5000; # Лимит описан в протоколе на sitemas.org

	$sitemap = array(); # Массив для предварительного накопления ссылок

	$CI = & get_instance();
	$CI->load->helper('file'); // хелпер для работы с файлами
		
	// временная зона сайта в формат +03:00 из 3.00
	$time_zone = getinfo('time_zone'); // 3.00 -11.00;
	$znak = ( (int) $time_zone >= 0) ? '+' : '-';
	$time_zone = abs($time_zone);
	if ($time_zone == 0) $time_zone = '0.0';
	$time_zone = trim( str_replace('.', ' ', $time_zone) );
	$time_z = explode(' ', $time_zone);
	if (!isset($time_z[0])) $time_z[0] = '0';
	if (!isset($time_z[1])) $time_z[1] = '0';
	if ($time_z[0] < 10) $time_z[0] = '0' . $time_z[0];
	if ($time_z[1] < 10) $time_z[1] = '0' . $time_z[1];
	$time_zone = $znak . $time_z[0] . ':' . $time_z[1];
		
	$url = getinfo('siteurl');

	if($options['url_protocol'])
	{
		$url = str_replace('http://', '', $url);
		$url = str_replace('https://', '', $url);
		$url = $options['url_protocol'] . $url;
	}

	#
	# Добавляем главную страницу (home)
	#
	$sitemap[] = array(
			'loc' 		=> $url,
			'lastmod'	=> date('Y-m-d').'T'.date('H:i:s').$time_zone,
			'changefreq'	=> $options['freq_priority']['home']['changefreq'],
			'priority'	=> $options['freq_priority']['home']['priority'],
			);
	
	#
	# Добавляем записи
	#
	// временная зона для запросов с page_date_publish
	$tz = getinfo('time_zone');
	if ($tz < 10 and $tz > 0) $tz = '0' . $tz;
	elseif ($tz > -10 and $tz < 0) 
	{ 
		$tz = '0' . $time_zone; 
		$tz = str_replace('0-', '-0', $time_zone); 
	}
	else $tz = '00.00';
	$tz = str_replace('.', ':', $tz);
		
	// страницы notblog
	$CI->db->select('page.page_id, page_slug, page_date_publish');
	$CI->db->from('page');

	if(count($options['page_cats_hide']) > 0) 
	{
		$CI->db->join('cat2obj', 'cat2obj.page_id = page.page_id', 'left');
		$CI->db->where('( category_id NOT IN ('.implode(',', $options['page_cats_hide']).') or category_id IS NULL )');
	}
	
	if(count($options['page_hide']) > 0) 
	{
		$CI->db->where_not_in('page.page_id', $options['page_hide']);
	}
	
	$CI->db->where('page_type_name !=', 'blog');
	$CI->db->where('page_status', 'publish');
	$CI->db->where('page_date_publish < ', 'DATE_ADD(NOW(), INTERVAL "' . $tz . '" HOUR_MINUTE)', false);
	//$CI->db->where('page_date_publish <', mso_date_convert('Y-m-d H:i:s', date('Y-m-d H:i:s')));
	
	$CI->db->join('page_type', 'page_type.page_type_id = page.page_type_id', 'left');
	$CI->db->order_by('page_date_publish', 'desc');
	$CI->db->group_by('page.page_id');
	
	$query = $CI->db->get();
	if ($query->num_rows()>0)
	{
		foreach ($query->result_array() as $row)
		{
			$date = str_replace(' ', 'T', $row['page_date_publish']) . $time_zone;
			
			$sitemap[] = array(
						'loc' 		=> $url.'page/'.$row['page_slug'],
						'lastmod'	=> $date,
						'changefreq'	=> $options['freq_priority']['notblog']['changefreq'],
						'priority'	=> $options['freq_priority']['notblog']['priority'],
					);
		}
	}
		
	// страницы blog
	$CI->db->select('page.page_id, page_slug, page_date_publish');
	$CI->db->from('page');
	
	if(count($options['page_cats_hide']) > 0) 
	{
		$CI->db->join('cat2obj', 'cat2obj.page_id = page.page_id', 'left');
		$CI->db->where('( category_id NOT IN ('.implode(',', $options['page_cats_hide']).') or category_id IS NULL )');
	}
	
	if(count($options['page_hide']) > 0) 
	{
		$CI->db->where_not_in('page.page_id', $options['page_hide']);
	}
	
	$CI->db->where('page_type_name', 'blog');
	$CI->db->where('page_status', 'publish');
	$CI->db->where('page_date_publish < ', 'DATE_ADD(NOW(), INTERVAL "' . $tz . '" HOUR_MINUTE)', false);
	$CI->db->join('page_type', 'page_type.page_type_id = page.page_type_id', 'left');
	$CI->db->group_by('page.page_id');
	$CI->db->order_by('page_date_publish', 'desc');
	$query = $CI->db->get();
	if ($query->num_rows()>0)
	{
		foreach ($query->result_array() as $row)
		{
			$date = str_replace(' ', 'T', $row['page_date_publish']) . $time_zone;

			$sitemap[] = array(
						'loc' 		=> $url.'page/'.$row['page_slug'],
						'lastmod'	=> $date,
						'changefreq'	=> $options['freq_priority']['blog']['changefreq'],
						'priority'	=> $options['freq_priority']['blog']['priority'],
					);
		}
	}

	// единая дата-время обновления урла
	$date = date('Y-m-d').'T'.date('H:i:s').$time_zone; 

	#
	# Добавляем рубрики
	#
	if(count($options['categories_show']) > 0) $CI->db->or_where_in('category_id', $options['categories_show']);
	$CI->db->where('category_type', 'page');
	
	$query = $CI->db->get('category');
	
	if ($query->num_rows()>0)
	{
		foreach ($query->result_array() as $row)
		{
			// $date = str_replace(' ', 'T', date('Y-m-d')) . $time_zone;

			$sitemap[] = array(
						'loc' 		=> $url.'category/'.$row['category_slug'],
						'lastmod'	=> $date,
						'changefreq'	=> $options['freq_priority']['category']['changefreq'],
						'priority'	=> $options['freq_priority']['category']['priority'],
					);
		}
	}		
	
	#
	# Добавляем метки
	#
	if($options['tags_show'])
	{		
		$alltags = mso_get_all_tags_page();
		
		foreach ($alltags as $tag => $count) 
		{
			$sitemap[] = array(
						'loc' 		=> $url.'tag/'.htmlentities(urlencode($tag)),
						'lastmod'	=> $date,
						'changefreq'	=> $options['freq_priority']['tag']['changefreq'],
						'priority'	=> $options['freq_priority']['tag']['priority'],
					);
		}
	}
	
	#
	# Добаляем комюзеров
	#	
	if($options['comusers_show'])
	{
		$CI->db->select('comusers_id');
		
		$query = $CI->db->get('comusers');
		
		if ($query->num_rows() > 0)	
		{	
			foreach ($query->result_array() as $row)
			{
				$sitemap[] = array(
							'loc' 		=> $url.'users/'.$row['comusers_id'],
							'lastmod'	=> $date,
							'changefreq'	=> $options['freq_priority']['comuser']['changefreq'],
							'priority'	=> $options['freq_priority']['comuser']['priority'],
						);
			}
		}
	}
		
        #
	# Добавялем юзеров (авторов)
	#
	if($options['users_show'])
	{
		$CI->db->select('users_id');
		
		$query = $CI->db->get('users');
		
		if ($query->num_rows() > 0)	
		{	
			foreach ($query->result_array() as $row)
			{
				$sitemap[] = array(
							'loc' 		=> $url.'author/'.$row['users_id'],
							'lastmod'	=> $date,
							'changefreq'	=> $options['freq_priority']['user']['changefreq'],
							'priority'	=> $options['freq_priority']['user']['priority'],
						);
			}
		}
	}
		
	#
	# Добавляем кастомные урлы
	#
	if($options['custom_urls'])
	{
		if( !isset($options['freq_priority']['notblog']['changefreq']) ) $options['freq_priority']['notblog']['changefreq'] = 'monthly';
		if( !isset($options['freq_priority']['notblog']['priority']) ) $options['freq_priority']['notblog']['priority'] = '0.7';
			
		foreach ($options['custom_urls'] as $url)
		{
			if( $url )
			{
				$url = parse_url($url, PHP_URL_PATH);
				$url = substr($url, 0, 1) == '/' ? substr($url, 1) : $url;
				$url = getinfo('site_url').$url;
				
				$sitemap[] = array(
							'loc' 		=> $url,
							'lastmod'	=> $date,
							'changefreq'	=> $options['freq_priority']['notblog']['changefreq'],
							'priority'	=> $options['freq_priority']['notblog']['priority'],
						);
			}
		}
	}
	
	// формирование sitemap.xml
	$out = '';

	if($sitemap)
	{
		if($options['sitemap-mode'] == 'simple' or ($options['sitemap-index-links'] and $options['sitemap-index-links'] > count($sitemap))) # простой вариант или если общее количество ссылок меньше 
		{
			$out .= '<?xml version="1.0" encoding="UTF-8"?>'.NR.'<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">'.NR;

			foreach($sitemap as $url)
			{
				$out .= '<url>'.NR;
				$out .= '<loc>'.$url['loc'].'</loc>'.NR;
				$out .= '<lastmod>'.$url['lastmod'].'</lastmod>'.NR;
				$out .= '<changefreq>'.$url['changefreq'].'</changefreq>'.NR;
				$out .= '<priority>'.$url['priority'].'</priority>'.NR;
				$out .= '</url>'.NR;
			}

			$out .= mso_hook('xml_sitemap'); # хук, если нужно добавить свои данные

			$out .= '</urlset>'.NR;

			file_put_contents(getinfo('FCPATH').'sitemap.xml', $out); # Сохраняем полный файл
		}
		else # вариант с разбиением sitemap.xml на части
		{
			$i = 1; 	# счётчик частей
			$indx = '';     # контент индексного файла
			$part = array();# массив ссылок для одной части sitemap
			
			do {
				$part = array_splice( $sitemap, 0, $options['sitemap-index-links'] ); # вырезаем из массива часть

				if($part) # Если массив ссылок не пуст, то записываем очередную часть sitemap.xml
				{
					# формируем содержимое "частичного" sitemap.xml
					$content = '<?xml version="1.0" encoding="UTF-8"?>'.NR.'<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">'.NR;
					foreach( $part as $k => $url )
					{
						$link = '';

						$link .= '<url>'.NR;
						$link .= '<loc>'.$url['loc'].'</loc>'.NR;
						$link .= '<lastmod>'.$url['lastmod'].'</lastmod>'.NR;
						$link .= '<changefreq>'.$url['changefreq'].'</changefreq>'.NR;
						$link .= '<priority>'.$url['priority'].'</priority>'.NR;
						$link .= '</url>'.NR;

						$content .= $link;
						$out .= $link;
					}
				
					$content .= '</urlset>'.NR;
	
					file_put_contents(getinfo('FCPATH').'sitemap-'.$i.'.xml', $content);

					# Формируем содержимое индексного sitemap-файла
					$indx .= '<sitemap>'.NR.'<loc>'.getinfo('siteurl').'sitemap-'.$i.'.xml</loc>'.NR.'<lastmod>'.date('Y-m-d').'T'.date('H:i:s').$time_zone.'</lastmod>'.NR.'</sitemap>'.NR;

					if($sitemap) $i++;
				}

			} while($part);

			# Сохраняем индексный sitemap-файл
			if($indx)
			{
				$content = '<?xml version="1.0" encoding="UTF-8"?>'.NR.'<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">'.NR.$indx.'</sitemapindex>'.NR;
				file_put_contents(getinfo('FCPATH').'sitemap.xml', $content); # Сохраняем индексный файл
			}

			if($options['sitemap-full'] == 'yes')
			{
				$out = mso_hook('xml_sitemap_conv', $out); # хук, если нужно как-то обработать результирующий файл. Например, разбить на части

				$out = '<?xml version="1.0" encoding="UTF-8"?>'.NR.'<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">'.NR.$out.'</urlset>'.NR;
			
				file_put_contents(getinfo('FCPATH').'sitemap-full.xml', $out); # Сохраняем полный файл
			}

		}
	}
		
	return $args; // для обеспечения цепочки хуков
}

# функция отрабатывающая миниопции плагина (function плагин_mso_options)
function xml_sitemap_mso_options()
{
	if(!mso_check_allow('xml_sitemap_to_hook_edit'))
	{
		echo t('Доступ запрещен');
		return;
	}
	
    # ключ, тип, ключи массива
    mso_admin_plugin_options('plugin_xml_sitemap', 'plugins', 
        array(
			'freq_priority' => array(
							'type' => 'textarea', 
							'name' => 'Приоритеты и частота обновления', 
							'description' => t('Укажите значения параметров <b>changefreq</b> и <b>priority</b> для разных групп страниц сайта по формату: Группа страниц | changefreq | priority<br>Допустимые группы страниц: home, notblog, blog, category, tag, comusers, users<br>Допустимые значения changefreq: always, hourly, daily, weekly, monthly, yearly, never<br>Допустимы значения priority: от 0.0 до 1.0'),
							'default' =>	'home | daily | 1' . NR .
									'notblog | monthly | 0.7' . NR . 
									'blog | weekly | 0.5' . NR .
									'category | weekly | 0.3' . NR.
									'tag | weekly | 0.3' . NR .
									'comuser | weekly | 0.3' . NR .
									'user | weekly | 0.3',
						),

			'tags_show' => array(
                            'type' => 'checkbox', 
                            'name' => t('Добавить страницы меток'),
                            'description' => '', 
                            'default' => 0,
							'group_start' => '<hr>',
						),
						
            'comusers_show' => array(
                            'type' => 'checkbox', 
                            'name' => t('Добавить страницы комюзеров (комментаторов)'), 
                            'description' => '', 
                            'default' => 0
                        ),
						
            'users_show' => array(
                            'type' => 'checkbox', 
                            'name' => t('Добавить страницы авторов'), 
                            'description' => '', 
                            'default' => 0,
							'group_end' => '<hr>',
                        ),
			
            'page_hide' => array(
                            'type' => 'text', 
                            'name' => t('Исключить страницы (записи)'), 
                            'description' => t('Перечислите через запятую ID записей, которые <b>не будут</b> добавлены в sitemap.xml'), 
                            'default' => ''
                        ),
						
            'page_cats_hide' => array(
                            'type' => 'text', 
                            'name' => t('Скрывать страницы из рубрик'), 
                            'description' => t('Перечислите через запятую ID рубрик, страницы из которых не попадут в sitemap.xml'), 
                            'default' => ''
                        ),
						
            'categories_show' => array(
                            'type' => 'text', 
                            'name' => t('Добавить страницы рубрик'), 
                            'description' => t('Перечислите через запятую ID рубрик, страницы которых будут добавлены в sitemap.xml. Оставьте поле пустым, если нужно добавить страницы всех имеющихся рубрик'), 
                            'default' => ''
                        ),
						
			'custom_urls' => array(
                            'type' => 'textarea', 
                            'name' => 'Кастомные адреса для добавления', 
                            'description' => t('Укажите (по одному в каждой строке) абсолютные или относительные адреса нестандартных страниц или файлов (например, DOCX-файл из папки UPLOADS) сайта, которые необходимо добавить в sitemap.xml. Для этих адресов будет использованы настройки приоритета и частоты от <b>notblog</b>.'),
                            'default' => '',
			),
						
			'url_protocol' => array(
                            'type' => 'select', 
                            'name' => t('HTTP протокол сайта'), 
                            'values' => '||Не менять # http://||http # https://||https',
                            'description' => t('Можно явно задать протокол сайт.'), 
                            'default' => ''
                        ),
				
			'sitemap-mode' => array(
                            'type' => 'select', 
                            'name' => t('Режим формирования sitemap.xml'), 
                            'values' => 'simple||Формировать единый файл#complex||Разбивать на части',
                            'description' => t('Выберите режим, который будет задавать принцип формирования файла sitemap.xml. Разбиение на части реализовано согласно <a href="https://www.sitemaps.org/ru/protocol.html#index" target=_blank>описанному протоколу</a>.'), 
                            'default' => 'simple'
                        ),

			'sitemap-index-links' => array(
				'type' => 'text',
				'name' => 'Количество ссылок в каждой части индексного sitemap.xml',
				'description' => 'Если sitemap.xml разбивается на части, то в данном поле можно задать количество ссылок, которые попадут в кажду часть. Максимум для одной части - 50000 ссылок.',
				'default' => '1000'
			),
						
			'sitemap-full' => array(
                            'type' => 'select', 
                            'name' => t('Сохранять единый файл при режиме разбиения sitemap.xml на части?'), 
                            'values' => 'yes||Да#no||Нет',
                            'description' => t('Для отладки и других работ может потребоваться версия sitemap.xml без разбиения на части. Если выбрать вариант "ДА", то будет сохраняться единый файл с именем sitemap-full.xml.'), 
                            'default' => 'no'
                        ),

            ),
		t('Настройки XML Sitemap'), # Заголовок страницы с настройками плагина
		
		t('C помощью настроек плагина можно настроить частоту и приоритет обновления информации о страницах, а также убрать вывод ненужных адресов страниц в файле <b>sitemap.xml</b> и тем самым уменьшить количество сообщений об ошибках индексации в панелях вебмастера в поисковых системах («<a href="http://webmaster.yandex.ru/">Яндекс.Вебмастер</a>» и «<a href="https://www.google.com/webmasters/tools/home?hl=ru">Инструменты для веб-мастеров в Google</a>»).')  // инфа
    );
		
	if ($_POST) xml_sitemap_custom();
}

# end of file