<commit_before><?php defined('ROOT') or die('No direct script access.');
/**
 * X3 CMS - A smart Content Management System
 *
 * @author		<NAME>
 * @copyright	(c) 2010-2015 CBlu.net di <NAME>
 * @license		http://www.gnu.org/licenses/agpl.htm
 * @package		X3CMS
 */

/**
 * Model for Page Items
 * The constructor set Area ID and Language code so each object lives within it
 *
 * @package X3CMS
 */
class Page_model extends X4Model_core
{
	/**
	 * @var integer Area ID
	 */
	protected $id_area;
	
	/**
	 * @var string	Language code
	 */
	protected $lang;
	
	/**
	 * @var string	URL of parent page
	 */
	protected $xfrom;
	
	/**
	 * @var object	Menu model
	 */
	protected $menu;
	
	/**
	 * Constructor
	 *
	 * @param integer	$id_area Area ID
	 * @param string	$lang Language code
	 * @param integer	$id_page Page ID
	 * @param string	$from Parent page URL
	 * @return  void
	 */
	public function __construct($id_area = 0, $lang = '', $id_page = 0, $from = '')
	{
		// set default table
		parent::__construct('pages');
		
		if ($id_page) 
		{
			// create object by Page ID
			$data = $this->db->query_row('SELECT p.id_area, p.lang, p.xfrom 
				FROM pages p 
				JOIN areas a ON a.id = p.id_area 
				WHERE p.id = '.intval($id_page));
			
			// override parameters
			$id_area = $data->id_area;
			$lang = $data->lang;
			$from = $data->xfrom;
		}
		
		// initialize object
		$this->id_area = $id_area;
		$this->lang = $lang;
		$this->xfrom = $from;
		$this->menu = new Menu_model();
	}
	
	/**
	 * Check if a page with the same URL already exists
	 *
	 * @param   string	$url URL to check
	 * @param   integer $id Page ID, if the page already exists
	 * @return  integer	the number of pages with the searched URL
	 */
	public function exists($url, $id = 0) 
	{
		// condition
		$where = ($id) 
			? ' AND id <> '.intval($id)
			: '';
		
		return $this->db->query_var('SELECT COUNT(id) 
			FROM pages 
			WHERE 
				id_area = '.intval($this->id_area).' AND 
				lang = '.$this->db->escape($this->lang).' AND 
				url = '.$this->db->escape($url).' '.$where);
	}
	
	/**
	 * Get Page by URL
	 *
	 * @param   string	$url Page URL
	 * @return  object
	 */
	public function get_page($url)
	{
		return $this->db->query_row('SELECT p.*, a.name AS area 
			FROM pages p 
			JOIN areas a ON a.id = p.id_area 
			WHERE 
				p.id_area = '.intval($this->id_area).' AND 
				p.lang = '.$this->db->escape($this->lang).' AND 
				p.url = '.$this->db->escape($url));
	}
	
	/**
	 * Get Page by ID
	 *
	 * @param   integer	$id Page ID
	 * @return  object
	 */
	public function get_page_by_id($id)
	{
		return $this->db->query_row('SELECT p.*, a.name AS area 
			FROM pages p
			JOIN areas a ON a.id = p.id_area 
			WHERE p.id = '.intval($id));
	}
	
	/**
	 * Get Parent URL by Page URL
	 *
	 * @param   string	$url Page URL
	 * @return  object
	 */
	public function get_from($url)
	{
		return $this->db->query_row('SELECT p.xfrom, p.url, p.name, p.description 
			FROM pages p
			JOIN areas a ON a.id = p.id_area 
			WHERE 
				p.id_area = '.intval($this->id_area).' AND
				p.lang = '.$this->db->escape($this->lang).' AND 
				p.url = '.$this->db->escape($url));
	}
	
	/**
	 * Get Pages by Parent URL and Deep
	 * The deep indicates the distance from the home page
	 * A sub page of the homepage has deep = 1
	 * A sub page of a subpage of the home has deep = 2 and so on
	 *
	 * @param   string	$xfrom Parent URL
	 * @param   integer	$deep Required Deep 
	 * @param   string	$diff Page URL to exclude
	 * @return  object
	 */
	public function get_pages($xfrom = '', $deep = 0, $diff = '' )
	{
		// conditions
		
		// correction for special case
		// the home have url and xfrom = home
		if ($xfrom == 'home')
		{
			$from = 'AND (p.url = \'home\' OR p.xfrom = \'home\')';
		}
		else if($deep)
		{
			$from = 'AND p.deep = '.($deep+1).' AND p.xfrom = '.$this->db->escape($xfrom);
		}
		else
		{
			$from = '';
		}
		
		// if isset diff exclude a page
		if (!empty($diff) && $diff != 'home') 
		{
			$from .= ' AND p.url <> '.$this->db->escape($diff);
		}
		
		return $this->db->query('SELECT DISTINCT p.*, a.title AS area, pr.level
			FROM pages p
			JOIN areas a ON a.id = p.id_area 
			JOIN privs pr ON pr.id_who = '.intval($_SESSION['xuid']).' AND pr.what = \'pages\' AND pr.id_what = p.id
			WHERE 
				p.id_area = '.intval($this->id_area).' AND 
				p.lang = '.$this->db->escape($this->lang).' 
				'.$from.'
			ORDER BY p.ordinal ASC, p.url ASC');
	}
	
	/**
	 * Update page data
	 * Updating the page must maintain the consistency of relations with the other pages
	 * After the update we have to refresh the sitemap.xml file
	 *
	 * @param   integer	$id Page ID
	 * @param   array	$array Post array 
	 * @param   string	$domain Domain name
	 * @return  array
	 */
	public function update_page($id, $array, $domain)
	{
		// build the update query
		$update = '';
		foreach($array as $k => $v) 
		{
			$update .= ', '.addslashes($k).' = '.$this->db->escape($v);
		}
		$sql = array();
		$sql[] = 'UPDATE pages SET updated = NOW() '.$update.' WHERE id = '.intval($id);
		
		// get page data (before the update)
		$page = $this->get_by_id($id);
		
		// if the Page URL is changed we need to update subpages data
		if (isset($array['url']) && $array['url'] != $page->url)
		{
			$sql[] = 'UPDATE pages SET xfrom = '.$this->db->escape($array['url']).'
				WHERE 
					id_area = '.$page->id_area.' AND 
					lang = '.$this->db->escape($page->lang).' AND 
					xfrom = '.$this->db->escape($page->url);
		}
		
		// if the parent page is changed we need to update xpos and deep
		if (isset($array['xfrom']) && $array['xfrom'] != $page->xfrom)
		{
			if ($array['xfrom'] == 'home') 
			{
				// simple case
				$sql[] = 'UPDATE pages SET updated = NOW(), id_menu = 0, xpos = 0, deep = 1 WHERE id = '.intval($id);
			}
			else 
			{
				// get new deep value
				$deep = $this->get_deep($array['xfrom']);
				$deep++;
				$sql[] = 'UPDATE pages SET updated = NOW(), id_menu = 0, xpos = 0, deep = '.$deep.' WHERE id = '.intval($id);
			}
			
			// we need to update the page order in which it was, the page now moved
			if ($page->xpos > 0) 
			{
				// reorder old xfrom
				$sql[] = 'UPDATE pages 
					SET updated = NOW(), xpos = (xpos - 1) 
					WHERE 
						id_area = '.$page->id_area.' AND 
						lang = '.$this->db->escape($page->lang).' AND 
						xfrom = '.$this->db->escape($page->xfrom).' AND 
						id_menu = '.$page->id_menu.' AND
						deep = '.$page->deep.' AND
						xpos > '.$page->xpos;
			}
		}
		
		// perform the update
		$result = $this->db->multi_exec($sql);
		
		// refresh deep, xpos and ordinal
		$this->menu->ordinal($page->id_area, $page->lang, 'home', 'A');
		
		// update sitemap.xml
		$this->update_sitemap($domain);
		
		return $result;
	}
	
	/**
	 * Insert a new page
	 * After the insertion we have to update the sitemap.xml file
	 *
	 * @param   array	$array Post array 
	 * @param   string	$domain Domain name
	 * @return  array
	 */
	public function insert_page($array, $domain)
	{
		// get deep
		$array['deep'] = $this->get_deep($array['xfrom']) + 1;
		
		// insert new page
		$res = $this->insert($array);
		
		// create a default article
		if ($res[1]) 
		{
			$data = array(
				'id_area' => $this->id_area,
				'lang' => $this->lang, 
				'bid' => md5(time().'-'.$_SESSION['xuid']),
				'id_page' => $res[0], 
				'name' => $array['name'],
				'code_context' => 1,
				'date_in' => time(),
				'id_editor' => $_SESSION['xuid']
			);
			
			// insert empty article
			$res_article = $this->insert($data, 'articles');
		}
		
		// refresh ordinal
		$this->menu->ordinal($this->id_area, $this->lang, 'home', 'A');
		
		// update sitemap.xml
		$this->update_sitemap($domain);
		
		return $res;
	}
	
	/**
	 * Get the depth of a page in the site tree by Parent URL
	 *
	 * @param   string	$xfrom Parent URL
	 * @return  integer
	 */
	private function get_deep($xfrom)
	{
		return (int) $this->db->query_var('SELECT deep FROM pages WHERE id_area = '.$this->db->escape($this->id_area).' AND lang = '.$this->db->escape($this->lang).' AND url = '.$this->db->escape($xfrom));
	}
	
	/**
	 * Initialize a new area
	 * Insert default pages (home, msg, x3admin, search and logout if the area is private)
	 * Insert default articles for each page
	 *
	 * @param   integer	$id_area Area ID
	 * @param   string	$lang Language code
	 * @param   array	$array Array of insert queries
	 * @return  array
	 */
	public function initialize_area($id_area, $lang, $array)
	{
		$sql = array();
		foreach($array as $i) 
		{
			// insert page
			$res = $this->insert($i[1]);
			
			// build query for related article
			if ($res[1])
				$sql[] = "INSERT INTO `articles` (`updated`, `bid`, `id_area`, `lang`, `code_context`, `name`, `id_page`, `id_editor`, `date_in`, `date_out`, `content`, `module`, `param`, `xlock`, `xon`) VALUES
					(NOW(), '".md5(time().'-'.$_SESSION['xuid'].$res[0])."', $id_area, '$lang', 1, '".$i[0]."', ".$res[0].", ".$_SESSION['xuid'].", UNIX_TIMESTAMP(), 0, '', '', '', 0, 1)";
		}
		
		// performs insertion of articles
		if (!empty($sql)) $res = $this->db->multi_exec($sql);
		return $res;
	}
	
	/**
	 * Initialize contexts
	 * When we create a new area we must also create necessary default contexts
	 *
	 * @param   integer	$id_area Area ID
	 * @param   string	$lang Language code
	 * @return  array
	 */
	public function initialize_context($id_area, $lang) 
	{
		$sql = array();
		$sql[] = 'INSERT INTO contexts (updated, id_area, lang, xkey, name, code, xlock, xon) VALUES (NOW(), '.intval($id_area).', '.$this->db->escape($lang).', \'drafts\', \'drafts\', 0, 0, 1)';
		$sql[] = 'INSERT INTO contexts (updated, id_area, lang, xkey, name, code, xlock, xon) VALUES (NOW(), '.intval($id_area).', '.$this->db->escape($lang).', \'pages\', \'pages\', 1, 0, 1)';
		$sql[] = 'INSERT INTO contexts (updated, id_area, lang, xkey, name, code, xlock, xon) VALUES (NOW(), '.intval($id_area).', '.$this->db->escape($lang).', \'multi\', \'multipages\', 2, 0, 1)';
		$res = $this->db->multi_exec($sql);
	}
	
	/**
	 * Delete a page
	 * After the deletion we have to update the sitemap.xml file
	 *
	 * @param   integer	$id Page ID
	 * @param   string	$domain Domain
	 * @return  array
	 */
	public function delete_page($id, $domain)
	{
		// get page data
		$page = $this->get_page_by_id($id);
		
		$sql = array();
		// delete related articles
		$sql[] = 'DELETE FROM articles WHERE id_page = '.intval($id);
		
		// delete the page
		$sql[] = 'DELETE FROM pages WHERE id = '.intval($id);
		
		// move up subpages
		$sql[] = 'UPDATE pages SET xfrom = '.$this->db->escape($page->xfrom).', deep = '.$this->db->escape($page->deep).', xpos = 0 WHERE id_area = '.$this->db->escape($page->id_area).' AND id_area = '.$this->db->escape($page->lang);
		
		$res = $this->db->multi_exec($sql);
		
		if ($res[1])
		{
			// refresh ordinals
			$this->menu->ordinal($page->id_area, $page->lang, 'home', 'A');
		
			// update sitemap.xml
			$this->update_sitemap($domain);
		}
		
		return $res;
	}
	
	/**
	 * Get articles by Page ID
	 *
	 * @param   integer	$id Page ID
	 * @param   boolean	$rows One or more than one result
	 * @return  array
	 */
	public function get_content_by_id($id, $rows = false) 
	{
		if ($rows) 
		{
			// get many rows (advanced editing)
			return $this->db->query('SELECT a.*, p.level 
				FROM articles a 
				JOIN privs p ON p.id_who = '.intval($_SESSION['xuid']).' AND p.what = \'articles\' AND p.id_what = a.id
				WHERE a.id_page = '.intval($id).' 
				ORDER BY a.id DESC');
		}
		else 
		{
			// get one row (simple editing)
			return $this->db->query_row('SELECT * FROM articles WHERE id_page = '.intval($id).' ORDER BY id DESC');
		}
	}
	
	/**
	 * Update sitemap.xml
	 *
	 * @param   string	$domain Domain name
	 * @return  void
	 */
	private function update_sitemap($domain)
	{
		// get pages
		$pages = $this->db->query('SELECT p.url, p.lang, DATE(a.updated) AS updated 
			FROM pages p
			JOIN articles a ON a.id_page = p.id
			JOIN alang l ON l.code = p.lang AND p.id_area = l.id_area
			WHERE l.xon = 1 AND p.id_area = 2 AND p.xon = 1 AND p.hidden = 0 AND a.xon = 1
			GROUP BY p.id
			ORDER BY p.lang ASC, p.ordinal ASC, a.updated DESC');
		
		// build xml
		$head = '<?xml version=\'1.0\' encoding=\'UTF-8\'?>
			<urlset xmlns="http://www.google.com/schemas/sitemap/0.84"
			xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
			xsi:schemaLocation="http://www.google.com/schemas/sitemap/0.84
			http://www.google.com/schemas/sitemap/0.84/sitemap.xsd">'.NL;
			
		$body = '';
		if ($pages) {
			foreach ($pages as $i)
			{
				switch($i->url) {
				case 'map': 
					$body .= '<url><loc>'.$domain.'/'.$i->lang.'/map</loc><lastmod>'.date('Y-m-d').'</lastmod></url>'.NL;
					break;
				case 'home':
					$body .= '<url><loc>'.$domain.'/'.$i->lang.'</loc><lastmod>'.$i->updated.'</lastmod></url>'.NL;
					break;
				default:
					$body .= '<url><loc>'.$domain.'/'.$i->lang.'/'.$i->url.'</loc><lastmod>'.$i->updated.'</lastmod></url>'.NL;
				}
			}
		}
		$body .= '</urlset>';
		
		// write file
		$check = file_put_contents(APATH.'files/sitemap.xml', $head.$body);
	}
	
	/**
	 * Get available templates<commit_msg>added check to avoid language code in the URL when website is not multilingual<commit_after><?php defined('ROOT') or die('No direct script access.');
/**
 * X3 CMS - A smart Content Management System
 *
 * @author		<NAME>
 * @copyright	(c) 2010-2015 CBlu.net di <NAME>
 * @license		http://www.gnu.org/licenses/agpl.htm
 * @package		X3CMS
 */

/**
 * Model for Page Items
 * The constructor set Area ID and Language code so each object lives within it
 *
 * @package X3CMS
 */
class Page_model extends X4Model_core
{
	/**
	 * @var integer Area ID
	 */
	protected $id_area;
	
	/**
	 * @var string	Language code
	 */
	protected $lang;
	
	/**
	 * @var string	URL of parent page
	 */
	protected $xfrom;
	
	/**
	 * @var object	Menu model
	 */
	protected $menu;
	
	/**
	 * Constructor
	 *
	 * @param integer	$id_area Area ID
	 * @param string	$lang Language code
	 * @param integer	$id_page Page ID
	 * @param string	$from Parent page URL
	 * @return  void
	 */
	public function __construct($id_area = 0, $lang = '', $id_page = 0, $from = '')
	{
		// set default table
		parent::__construct('pages');
		
		if ($id_page) 
		{
			// create object by Page ID
			$data = $this->db->query_row('SELECT p.id_area, p.lang, p.xfrom 
				FROM pages p 
				JOIN areas a ON a.id = p.id_area 
				WHERE p.id = '.intval($id_page));
			
			// override parameters
			$id_area = $data->id_area;
			$lang = $data->lang;
			$from = $data->xfrom;
		}
		
		// initialize object
		$this->id_area = $id_area;
		$this->lang = $lang;
		$this->xfrom = $from;
		$this->menu = new Menu_model();
	}
	
	/**
	 * Check if a page with the same URL already exists
	 *
	 * @param   string	$url URL to check
	 * @param   integer $id Page ID, if the page already exists
	 * @return  integer	the number of pages with the searched URL
	 */
	public function exists($url, $id = 0) 
	{
		// condition
		$where = ($id) 
			? ' AND id <> '.intval($id)
			: '';
		
		return $this->db->query_var('SELECT COUNT(id) 
			FROM pages 
			WHERE 
				id_area = '.intval($this->id_area).' AND 
				lang = '.$this->db->escape($this->lang).' AND 
				url = '.$this->db->escape($url).' '.$where);
	}
	
	/**
	 * Get Page by URL
	 *
	 * @param   string	$url Page URL
	 * @return  object
	 */
	public function get_page($url)
	{
		return $this->db->query_row('SELECT p.*, a.name AS area 
			FROM pages p 
			JOIN areas a ON a.id = p.id_area 
			WHERE 
				p.id_area = '.intval($this->id_area).' AND 
				p.lang = '.$this->db->escape($this->lang).' AND 
				p.url = '.$this->db->escape($url));
	}
	
	/**
	 * Get Page by ID
	 *
	 * @param   integer	$id Page ID
	 * @return  object
	 */
	public function get_page_by_id($id)
	{
		return $this->db->query_row('SELECT p.*, a.name AS area 
			FROM pages p
			JOIN areas a ON a.id = p.id_area 
			WHERE p.id = '.intval($id));
	}
	
	/**
	 * Get Parent URL by Page URL
	 *
	 * @param   string	$url Page URL
	 * @return  object
	 */
	public function get_from($url)
	{
		return $this->db->query_row('SELECT p.xfrom, p.url, p.name, p.description 
			FROM pages p
			JOIN areas a ON a.id = p.id_area 
			WHERE 
				p.id_area = '.intval($this->id_area).' AND
				p.lang = '.$this->db->escape($this->lang).' AND 
				p.url = '.$this->db->escape($url));
	}
	
	/**
	 * Get Pages by Parent URL and Deep
	 * The deep indicates the distance from the home page
	 * A sub page of the homepage has deep = 1
	 * A sub page of a subpage of the home has deep = 2 and so on
	 *
	 * @param   string	$xfrom Parent URL
	 * @param   integer	$deep Required Deep 
	 * @param   string	$diff Page URL to exclude
	 * @return  object
	 */
	public function get_pages($xfrom = '', $deep = 0, $diff = '' )
	{
		// conditions
		
		// correction for special case
		// the home have url and xfrom = home
		if ($xfrom == 'home')
		{
			$from = 'AND (p.url = \'home\' OR p.xfrom = \'home\')';
		}
		else if($deep)
		{
			$from = 'AND p.deep = '.($deep+1).' AND p.xfrom = '.$this->db->escape($xfrom);
		}
		else
		{
			$from = '';
		}
		
		// if isset diff exclude a page
		if (!empty($diff) && $diff != 'home') 
		{
			$from .= ' AND p.url <> '.$this->db->escape($diff);
		}
		
		return $this->db->query('SELECT DISTINCT p.*, a.title AS area, pr.level
			FROM pages p
			JOIN areas a ON a.id = p.id_area 
			JOIN privs pr ON pr.id_who = '.intval($_SESSION['xuid']).' AND pr.what = \'pages\' AND pr.id_what = p.id
			WHERE 
				p.id_area = '.intval($this->id_area).' AND 
				p.lang = '.$this->db->escape($this->lang).' 
				'.$from.'
			ORDER BY p.ordinal ASC, p.url ASC');
	}
	
	/**
	 * Update page data
	 * Updating the page must maintain the consistency of relations with the other pages
	 * After the update we have to refresh the sitemap.xml file
	 *
	 * @param   integer	$id Page ID
	 * @param   array	$array Post array 
	 * @param   string	$domain Domain name
	 * @return  array
	 */
	public function update_page($id, $array, $domain)
	{
		// build the update query
		$update = '';
		foreach($array as $k => $v) 
		{
			$update .= ', '.addslashes($k).' = '.$this->db->escape($v);
		}
		$sql = array();
		$sql[] = 'UPDATE pages SET updated = NOW() '.$update.' WHERE id = '.intval($id);
		
		// get page data (before the update)
		$page = $this->get_by_id($id);
		
		// if the Page URL is changed we need to update subpages data
		if (isset($array['url']) && $array['url'] != $page->url)
		{
			$sql[] = 'UPDATE pages SET xfrom = '.$this->db->escape($array['url']).'
				WHERE 
					id_area = '.$page->id_area.' AND 
					lang = '.$this->db->escape($page->lang).' AND 
					xfrom = '.$this->db->escape($page->url);
		}
		
		// if the parent page is changed we need to update xpos and deep
		if (isset($array['xfrom']) && $array['xfrom'] != $page->xfrom)
		{
			if ($array['xfrom'] == 'home') 
			{
				// simple case
				$sql[] = 'UPDATE pages SET updated = NOW(), id_menu = 0, xpos = 0, deep = 1 WHERE id = '.intval($id);
			}
			else 
			{
				// get new deep value
				$deep = $this->get_deep($array['xfrom']);
				$deep++;
				$sql[] = 'UPDATE pages SET updated = NOW(), id_menu = 0, xpos = 0, deep = '.$deep.' WHERE id = '.intval($id);
			}
			
			// we need to update the page order in which it was, the page now moved
			if ($page->xpos > 0) 
			{
				// reorder old xfrom
				$sql[] = 'UPDATE pages 
					SET updated = NOW(), xpos = (xpos - 1) 
					WHERE 
						id_area = '.$page->id_area.' AND 
						lang = '.$this->db->escape($page->lang).' AND 
						xfrom = '.$this->db->escape($page->xfrom).' AND 
						id_menu = '.$page->id_menu.' AND
						deep = '.$page->deep.' AND
						xpos > '.$page->xpos;
			}
		}
		
		// perform the update
		$result = $this->db->multi_exec($sql);
		
		// refresh deep, xpos and ordinal
		$this->menu->ordinal($page->id_area, $page->lang, 'home', 'A');
		
		// update sitemap.xml
		$this->update_sitemap($domain);
		
		return $result;
	}
	
	/**
	 * Insert a new page
	 * After the insertion we have to update the sitemap.xml file
	 *
	 * @param   array	$array Post array 
	 * @param   string	$domain Domain name
	 * @return  array
	 */
	public function insert_page($array, $domain)
	{
		// get deep
		$array['deep'] = $this->get_deep($array['xfrom']) + 1;
		
		// insert new page
		$res = $this->insert($array);
		
		// create a default article
		if ($res[1]) 
		{
			$data = array(
				'id_area' => $this->id_area,
				'lang' => $this->lang, 
				'bid' => md5(time().'-'.$_SESSION['xuid']),
				'id_page' => $res[0], 
				'name' => $array['name'],
				'code_context' => 1,
				'date_in' => time(),
				'id_editor' => $_SESSION['xuid']
			);
			
			// insert empty article
			$res_article = $this->insert($data, 'articles');
		}
		
		// refresh ordinal
		$this->menu->ordinal($this->id_area, $this->lang, 'home', 'A');
		
		// update sitemap.xml
		$this->update_sitemap($domain);
		
		return $res;
	}
	
	/**
	 * Get the depth of a page in the site tree by Parent URL
	 *
	 * @param   string	$xfrom Parent URL
	 * @return  integer
	 */
	private function get_deep($xfrom)
	{
		return (int) $this->db->query_var('SELECT deep FROM pages WHERE id_area = '.$this->db->escape($this->id_area).' AND lang = '.$this->db->escape($this->lang).' AND url = '.$this->db->escape($xfrom));
	}
	
	/**
	 * Initialize a new area
	 * Insert default pages (home, msg, x3admin, search and logout if the area is private)
	 * Insert default articles for each page
	 *
	 * @param   integer	$id_area Area ID
	 * @param   string	$lang Language code
	 * @param   array	$array Array of insert queries
	 * @return  array
	 */
	public function initialize_area($id_area, $lang, $array)
	{
		$sql = array();
		foreach($array as $i) 
		{
			// insert page
			$res = $this->insert($i[1]);
			
			// build query for related article
			if ($res[1])
				$sql[] = "INSERT INTO `articles` (`updated`, `bid`, `id_area`, `lang`, `code_context`, `name`, `id_page`, `id_editor`, `date_in`, `date_out`, `content`, `module`, `param`, `xlock`, `xon`) VALUES
					(NOW(), '".md5(time().'-'.$_SESSION['xuid'].$res[0])."', $id_area, '$lang', 1, '".$i[0]."', ".$res[0].", ".$_SESSION['xuid'].", UNIX_TIMESTAMP(), 0, '', '', '', 0, 1)";
		}
		
		// performs insertion of articles
		if (!empty($sql)) $res = $this->db->multi_exec($sql);
		return $res;
	}
	
	/**
	 * Initialize contexts
	 * When we create a new area we must also create necessary default contexts
	 *
	 * @param   integer	$id_area Area ID
	 * @param   string	$lang Language code
	 * @return  array
	 */
	public function initialize_context($id_area, $lang) 
	{
		$sql = array();
		$sql[] = 'INSERT INTO contexts (updated, id_area, lang, xkey, name, code, xlock, xon) VALUES (NOW(), '.intval($id_area).', '.$this->db->escape($lang).', \'drafts\', \'drafts\', 0, 0, 1)';
		$sql[] = 'INSERT INTO contexts (updated, id_area, lang, xkey, name, code, xlock, xon) VALUES (NOW(), '.intval($id_area).', '.$this->db->escape($lang).', \'pages\', \'pages\', 1, 0, 1)';
		$sql[] = 'INSERT INTO contexts (updated, id_area, lang, xkey, name, code, xlock, xon) VALUES (NOW(), '.intval($id_area).', '.$this->db->escape($lang).', \'multi\', \'multipages\', 2, 0, 1)';
		$res = $this->db->multi_exec($sql);
	}
	
	/**
	 * Delete a page
	 * After the deletion we have to update the sitemap.xml file
	 *
	 * @param   integer	$id Page ID
	 * @param   string	$domain Domain
	 * @return  array
	 */
	public function delete_page($id, $domain)
	{
		// get page data
		$page = $this->get_page_by_id($id);
		
		$sql = array();
		// delete related articles
		$sql[] = 'DELETE FROM articles WHERE id_page = '.intval($id);
		
		// delete the page
		$sql[] = 'DELETE FROM pages WHERE id = '.intval($id);
		
		// move up subpages
		$sql[] = 'UPDATE pages SET xfrom = '.$this->db->escape($page->xfrom).', deep = '.$this->db->escape($page->deep).', xpos = 0 WHERE id_area = '.$this->db->escape($page->id_area).' AND id_area = '.$this->db->escape($page->lang);
		
		$res = $this->db->multi_exec($sql);
		
		if ($res[1])
		{
			// refresh ordinals
			$this->menu->ordinal($page->id_area, $page->lang, 'home', 'A');
		
			// update sitemap.xml
			$this->update_sitemap($domain);
		}
		
		return $res;
	}
	
	/**
	 * Get articles by Page ID
	 *
	 * @param   integer	$id Page ID
	 * @param   boolean	$rows One or more than one result
	 * @return  array
	 */
	public function get_content_by_id($id, $rows = false) 
	{
		if ($rows) 
		{
			// get many rows (advanced editing)
			return $this->db->query('SELECT a.*, p.level 
				FROM articles a 
				JOIN privs p ON p.id_who = '.intval($_SESSION['xuid']).' AND p.what = \'articles\' AND p.id_what = a.id
				WHERE a.id_page = '.intval($id).' 
				ORDER BY a.id DESC');
		}
		else 
		{
			// get one row (simple editing)
			return $this->db->query_row('SELECT * FROM articles WHERE id_page = '.intval($id).' ORDER BY id DESC');
		}
	}
	
	/**
	 * Update sitemap.xml
	 *
	 * @param   string	$domain Domain name
	 * @return  void
	 */
	private function update_sitemap($domain)
	{
		// get pages
		$pages = $this->db->query('SELECT p.url, p.lang, DATE(a.updated) AS updated 
			FROM pages p
			JOIN articles a ON a.id_page = p.id
			JOIN alang l ON l.code = p.lang AND p.id_area = l.id_area
			WHERE l.xon = 1 AND p.id_area = 2 AND p.xon = 1 AND p.hidden = 0 AND a.xon = 1
			GROUP BY p.id
			ORDER BY p.lang ASC, p.ordinal ASC, a.updated DESC');
		
		// build xml
		$head = '<?xml version=\'1.0\' encoding=\'UTF-8\'?>
			<urlset xmlns="http://www.google.com/schemas/sitemap/0.84"
			xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
			xsi:schemaLocation="http://www.google.com/schemas/sitemap/0.84
			http://www.google.com/schemas/sitemap/0.84/sitemap.xsd">'.NL;
			
		$body = '';
		if ($pages) {
		    
		    $domain = (MULTILANGUAGE)
		        ? $domain.'/'.$i->lang
		        : $domain;
		    
			foreach ($pages as $i)
			{
				switch($i->url) {
				case 'map': 
					$body .= '<url><loc>'.$domain.'/map</loc><lastmod>'.date('Y-m-d').'</lastmod></url>'.NL;
					break;
				case 'home':
					$body .= '<url><loc>'.$domain.'</loc><lastmod>'.$i->updated.'</lastmod></url>'.NL;
					break;
				default:
					$body .= '<url><loc>'.$domain.'/'.$i->url.'</loc><lastmod>'.$i->updated.'</lastmod></url>'.NL;
				}
			}
		}
		$body .= '</urlset>';
		
		// write file
		$check = file_put_contents(APATH.'files/sitemap.xml', $head.$body);
	}
	
	/**
	 * Get available templates
{'fraction_non_alphanumeric': 0.1873012267151295, 'fraction_numerical': 0.005679236710586098, 'mean_word_length': 2.700854700854701, 'pattern_counts': {'":': 0, '<': 55, '<?xml version=': 2, '>': 357, 'https://': 0, 'lorem ipsum': 0, 'www.': 10, 'xml': 24}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4763731', 'n_tokens_mistral': 11078, 'n_tokens_neox': 9419, 'n_words': 2644}