<commit_before><?php
/**
 * This file is part of MeCms.
 *
 * MeCms is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * MeCms is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with MeCms.  If not, see <http://www.gnu.org/licenses/>.
 *
 * @author		<NAME> <<EMAIL>>
 * @copyright	Copyright (c) 2016, <NAME> for Nova Atlantis Ltd
 * @license	http://www.gnu.org/licenses/agpl.txt AGPL License
 * @link		http://git.novatlantis.it Nova Atlantis Ltd
 */
namespace MeCms\Controller;

use Cake\I18n\Time;
use MeCms\Controller\AppController;
use MeTools\Cache\Cache;

/**
 * Posts controller
 * @property \MeCms\Model\Table\PostsTable $Posts
 */
class PostsController extends AppController {
	/**
	 * Called before the controller action. 
	 * You can use this method to perform logic that needs to happen before each controller action.
	 * @param \Cake\Event\Event $event An Event instance
	 * @see http://api.cakephp.org/3.2/class-Cake.Controller.Controller.html#_beforeFilter
	 * @uses MeCms\Controller\AppController::beforeFilter()
	 * @uses MeTools\Network\Request::isAction()
	 */
	public function beforeFilter(\Cake\Event\Event $event) {
        parent::beforeFilter($event);
        
        //View posts. It checks created datetime and status. Logged users can view future objects and drafts
		if($this->request->isAction('view')) {
            if($this->Auth->user()) {
                return;
            }
            
            $slug = $this->request->param('slug');
            
            $post = $this->Posts->find()
                ->select(['active', 'created'])
                ->where(compact('slug'))
                ->cache(sprintf('status_%s', md5($slug)), $this->Posts->cache)
                ->firstOrFail();
            
            if($post->active && $post->created->isPast()) {
                return;
            }
            
            $this->Auth->deny('view');
        }
    }
    
	/**
     * Lists posts
	 * @uses MeCms\Model\Table\PostsTable::checkIfCacheIsValid()
	 */
    public function index() {
		//Checks if the cache is valid
		$this->Posts->checkIfCacheIsValid();
		
		//Sets the cache name
		$cache = sprintf('index_limit_%s_page_%s', $this->paginate['limit'], $this->request->query('page') ? $this->request->query('page') : 1);
		
		//Tries to get data from the cache
		list($posts, $paging) = array_values(Cache::readMany([$cache, sprintf('%s_paging', $cache)], $this->Posts->cache));
		
		//If the data are not available from the cache
		if(empty($posts) || empty($paging)) {
			$posts = $this->paginate(
				$this->Posts->find('active')
					->contain([
						'Categories'	=> ['fields' => ['title', 'slug']],
						'Tags'			=> function($q) {
							return $q->order([sprintf('%s.post_count', $this->Posts->Tags->alias()) => 'DESC']);
						},
						'Users'			=> ['fields' => ['first_name', 'last_name']]
					])
					->select(['id', 'title', 'subtitle', 'slug', 'text', 'created'])
					->order([sprintf('%s.created', $this->Posts->alias()) => 'DESC'])
			)->toArray();
						
			//Writes on cache
			Cache::writeMany([$cache => $posts, sprintf('%s_paging', $cache) => $this->request->param('paging')], $this->Posts->cache);
		}
		//Else, sets the paging parameter
		else
			$this->request->params['paging'] = $paging;
		
        $this->set(compact('posts'));
    }
	
	/**
	 * Lists posts by a date
	 * @param int $year Year
	 * @param int $month Month
	 * @param int $day Day
	 * @uses MeCms\Model\Table\PostsTable::checkIfCacheIsValid()
	 */
	public function index_by_date($year, $month, $day) {
		//Checks if the cache is valid
		$this->Posts->checkIfCacheIsValid();
		
		//Sets the cache name
		$cache = sprintf('index_date_%s_limit_%s_page_%s', md5(serialize([$year, $month, $day])), $this->paginate['limit'], $this->request->query('page') ? $this->request->query('page') : 1);
		
		//Tries to get data from the cache
		list($posts, $paging) = array_values(Cache::readMany([$cache, sprintf('%s_paging', $cache)], $this->Posts->cache));
		
		//If the data are not available from the cache
		if(empty($posts) || empty($paging)) {		
			$posts = $this->paginate(
				$this->Posts->find('active')
					->contain([
						'Categories'	=> ['fields' => ['title', 'slug']],
						'Tags',
						'Users'			=> ['fields' => ['first_name', 'last_name']]
					])
					->select(['id', 'title', 'subtitle', 'slug', 'text', 'created'])
					->where([
						sprintf('%s.created >=', $this->Posts->alias()) => (new Time())->setDate($year, $month, $day)->setTime(0, 0, 0)->i18nFormat(FORMAT_FOR_MYSQL),
						sprintf('%s.created <=', $this->Posts->alias()) => (new Time())->setDate($year, $month, $day)->setTime(23, 59, 59)->i18nFormat(FORMAT_FOR_MYSQL)
					])
					->order([sprintf('%s.created', $this->Posts->alias()) => 'DESC'])
			)->toArray();
						
			//Writes on cache
			Cache::writeMany([$cache => $posts, sprintf('%s_paging', $cache) => $this->request->param('paging')], $this->Posts->cache);
		}
		//Else, sets the paging parameter
		else
			$this->request->params['paging'] = $paging;
		
        $this->set(compact('posts'));
		
		$this->render('Posts/index');
	}
	
	/**
	 * This allows backward compatibility for URLs like:
	 * <pre>/posts/page:3</pre>
	 * <pre>/posts/page:3/sort:Post.created/direction:desc</pre>
	 * These URLs will become:
	 * <pre>/posts?page=3</pre>
	 * @param int $page Page number
	 */
	public function index_compatibility($page) {
		return $this->redirect(['_name' => 'posts', '?' => ['page' => $page]], 301);
	}
	
	/**
	 * Lists posts as RSS
	 * @throws \Cake\Network\Exception\ForbiddenException
	 * @uses MeCms\Model\Table\PostsTable::checkIfCacheIsValid()
	 */
	public function rss() {
		//This method works only for RSS
		if(!$this->RequestHandler->isRss())
            throw new \Cake\Network\Exception\ForbiddenException();
		
		//Checks if the cache is valid
		$this->Posts->checkIfCacheIsValid();
		
		$this->set('posts', $this->Posts->find('active')
			->select(['title', 'slug', 'text', 'created'])
			->limit(config('frontend.records_for_rss'))
			->order([sprintf('%s.created', $this->Posts->alias()) => 'DESC'])
			->cache('rss', $this->Posts->cache));
		
		$this->viewBuilder()->layout('MeCms.frontend');
	}
	
	/**
	 * Search posts
	 * @uses MeCms\Controller\AppController::_checkLastSearch()
	 * @uses MeCms\Model\Table\PostsTable::checkIfCacheIsValid()
	 */
	public function search() {
        $pattern = $this->request->query('p');
        
		if($pattern) {
			//Checks if the pattern is at least 4 characters long
			if(strlen($pattern) >= 4) {
				if($this->_checkLastSearch($pattern)) {
					$this->paginate['limit'] = config('frontend.records_for_searches');
					
					//Checks if the cache is valid
					$this->Posts->checkIfCacheIsValid();
					
					//Sets the initial cache name
					$cache = sprintf('search_%s', md5($pattern));

					//Updates the cache name with the query limit and the number of the page
					$cache = sprintf('%s_limit_%s', $cache, $this->paginate['limit']);
					$cache = sprintf('%s_page_%s', $cache, $this->request->query('page') ? $this->request->query('page') : 1);<commit_msg>fixed typo<commit_after><?php
/**
 * This file is part of MeCms.
 *
 * MeCms is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * MeCms is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with MeCms.  If not, see <http://www.gnu.org/licenses/>.
 *
 * @author		<NAME> <<EMAIL>>
 * @copyright	Copyright (c) 2016, <NAME> for Nova Atlantis Ltd
 * @license	http://www.gnu.org/licenses/agpl.txt AGPL License
 * @link		http://git.novatlantis.it Nova Atlantis Ltd
 */
namespace MeCms\Controller;

use Cake\I18n\Time;
use MeCms\Controller\AppController;
use MeTools\Cache\Cache;

/**
 * Posts controller
 * @property \MeCms\Model\Table\PostsTable $Posts
 */
class PostsController extends AppController {
	/**
	 * Called before the controller action. 
	 * You can use this method to perform logic that needs to happen before each controller action.
	 * @param \Cake\Event\Event $event An Event instance
	 * @see http://api.cakephp.org/3.2/class-Cake.Controller.Controller.html#_beforeFilter
	 * @uses MeCms\Controller\AppController::beforeFilter()
	 * @uses MeTools\Network\Request::isAction()
	 */
	public function beforeFilter(\Cake\Event\Event $event) {
        parent::beforeFilter($event);
        
        //View posts. It checks created datetime and status. Logged users can view future objects and drafts
		if($this->request->isAction('view')) {
            if($this->Auth->user()) {
                return;
            }
            
            $slug = $this->request->param('slug');
            
            $post = $this->Posts->find()
                ->select(['active', 'created'])
                ->where(compact('slug'))
                ->cache(sprintf('status_%s', md5($slug)), $this->Posts->cache)
                ->firstOrFail();
            
            if($post->active && $post->created->isPast()) {
                return;
            }
            
            $this->Auth->deny('view');
        }
    }
    
	/**
     * Lists posts
	 * @uses MeCms\Model\Table\PostsTable::checkIfCacheIsValid()
	 */
    public function index() {
		//Checks if the cache is valid
		$this->Posts->checkIfCacheIsValid();
		
		//Sets the cache name
		$cache = sprintf('index_limit_%s_page_%s', $this->paginate['limit'], $this->request->query('page') ? $this->request->query('page') : 1);
		
		//Tries to get data from the cache
		list($posts, $paging) = array_values(Cache::readMany([$cache, sprintf('%s_paging', $cache)], $this->Posts->cache));
		
		//If the data are not available from the cache
		if(empty($posts) || empty($paging)) {
			$posts = $this->paginate(
				$this->Posts->find('active')
					->contain([
						'Categories'	=> ['fields' => ['title', 'slug']],
						'Tags'			=> function($q) {
							return $q->order([sprintf('%s.post_count', $this->Posts->Tags->alias()) => 'DESC']);
						},
						'Users'			=> ['fields' => ['first_name', 'last_name']]
					])
					->select(['id', 'title', 'subtitle', 'slug', 'text', 'created'])
					->order([sprintf('%s.created', $this->Posts->alias()) => 'DESC'])
			)->toArray();
						
			//Writes on cache
			Cache::writeMany([$cache => $posts, sprintf('%s_paging', $cache) => $this->request->param('paging')], $this->Posts->cache);
		}
		//Else, sets the paging parameter
		else
			$this->request->params['paging'] = $paging;
		
        $this->set(compact('posts'));
    }
	
	/**
	 * Lists posts by a date
	 * @param int $year Year
	 * @param int $month Month
	 * @param int $day Day
	 * @uses MeCms\Model\Table\PostsTable::checkIfCacheIsValid()
	 */
	public function index_by_date($year, $month, $day) {
		//Checks if the cache is valid
		$this->Posts->checkIfCacheIsValid();
		
		//Sets the cache name
		$cache = sprintf('index_date_%s_limit_%s_page_%s', md5(serialize([$year, $month, $day])), $this->paginate['limit'], $this->request->query('page') ? $this->request->query('page') : 1);
		
		//Tries to get data from the cache
		list($posts, $paging) = array_values(Cache::readMany([$cache, sprintf('%s_paging', $cache)], $this->Posts->cache));
		
		//If the data are not available from the cache
		if(empty($posts) || empty($paging)) {		
			$posts = $this->paginate(
				$this->Posts->find('active')
					->contain([
						'Categories'	=> ['fields' => ['title', 'slug']],
						'Tags',
						'Users'			=> ['fields' => ['first_name', 'last_name']]
					])
					->select(['id', 'title', 'subtitle', 'slug', 'text', 'created'])
					->where([
						sprintf('%s.created >=', $this->Posts->alias()) => (new Time())->setDate($year, $month, $day)->setTime(0, 0, 0)->i18nFormat(FORMAT_FOR_MYSQL),
						sprintf('%s.created <=', $this->Posts->alias()) => (new Time())->setDate($year, $month, $day)->setTime(23, 59, 59)->i18nFormat(FORMAT_FOR_MYSQL)
					])
					->order([sprintf('%s.created', $this->Posts->alias()) => 'DESC'])
			)->toArray();
						
			//Writes on cache
			Cache::writeMany([$cache => $posts, sprintf('%s_paging', $cache) => $this->request->param('paging')], $this->Posts->cache);
		}
		//Else, sets the paging parameter
		else
			$this->request->params['paging'] = $paging;
		
        $this->set(compact('posts'));
		
		$this->render('Posts/index');
	}
	
	/**
	 * This allows backward compatibility for URLs like:
	 * <pre>/posts/page:3</pre>
	 * <pre>/posts/page:3/sort:Post.created/direction:desc</pre>
	 * These URLs will become:
	 * <pre>/posts?page=3</pre>
	 * @param int $page Page number
	 */
	public function index_compatibility($page) {
		return $this->redirect(['_name' => 'posts', '?' => ['page' => $page]], 301);
	}
	
	/**
	 * Lists posts as RSS
	 * @throws \Cake\Network\Exception\ForbiddenException
	 * @uses MeCms\Model\Table\PostsTable::checkIfCacheIsValid()
	 */
	public function rss() {
		//This method works only for RSS
		if(!$this->RequestHandler->isRss())
            throw new \Cake\Network\Exception\ForbiddenException();
		
		//Checks if the cache is valid
		$this->Posts->checkIfCacheIsValid();
		
		$this->set('posts', $this->Posts->find('active')
			->select(['title', 'slug', 'text', 'created'])
			->limit(config('frontend.records_for_rss'))
			->order([sprintf('%s.created', $this->Posts->alias()) => 'DESC'])
			->cache('rss', $this->Posts->cache));
		
		$this->viewBuilder()->layout('MeCms.frontend');
	}
	
	/**
	 * Searches posts
	 * @uses MeCms\Controller\AppController::_checkLastSearch()
	 * @uses MeCms\Model\Table\PostsTable::checkIfCacheIsValid()
	 */
	public function search() {
        $pattern = $this->request->query('p');
        
		if($pattern) {
			//Checks if the pattern is at least 4 characters long
			if(strlen($pattern) >= 4) {
				if($this->_checkLastSearch($pattern)) {
					$this->paginate['limit'] = config('frontend.records_for_searches');
					
					//Checks if the cache is valid
					$this->Posts->checkIfCacheIsValid();
					
					//Sets the initial cache name
					$cache = sprintf('search_%s', md5($pattern));

					//Updates the cache name with the query limit and the number of the page
					$cache = sprintf('%s_limit_%s', $cache, $this->paginate['limit']);
					$cache = sprintf('%s_page_%s', $cache, $this->request->query('page') ? $this->request->query('page') : 1);
{'fraction_non_alphanumeric': 0.1851925236113863, 'fraction_numerical': 0.0047553001783237564, 'mean_word_length': 3.2653521126760565, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 301, 'https://': 0, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, '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': '228635', 'n_tokens_mistral': 5461, 'n_tokens_neox': 4769, 'n_words': 1144}