<commit_before><?php

namespace App\Models;

use App\Exceptions\UnpublishedParentException;
use DB;
use Doctrine\DBAL\Version;
use Exception;
use App\Models\Definitions\Layout as LayoutDefinition;
use Baum\Node as BaumNode;
use Illuminate\Database\Eloquent\Collection;
use League\Fractal\TransformerAbstract;

/**
 * A Page represents a path in a hierarchical site structure.
 * Each page has a current revision, and each "tree" of pages is scoped by its site_id and version (draft, published, etc).
 *
 * @package App\Models
 */
class Page extends BaumNode
{
	public $table = 'pages';

	public $timestamps = false;

	protected $fillable = [
		'slug',
		'draft_id',
		'parent_id',
		'site_id',
		'version',
		'path',
		'revision_id',
		'created_by',
		'updated_by',
	];

	protected $hidden = [
		'lft',
		'rgt'
	];

	// nested set implementation has a tree for each site_id+version combination.
	protected $scoped = ['site_id', 'version'];

	// The draft state of this page.
	const STATE_NEW = 'new'; // not published
	const STATE_DRAFT = 'draft'; // modified since last published
	const STATE_DELETED = 'deleted'; // deleted since last published
	const STATE_MOVED = 'moved'; // moved since last published
	const STATE_PUBLISHED = 'published'; // not modified since last published
	const STATE_EMPTY = 'empty'; // no draft or published state.


	/**
	 * Create a new Eloquent model instance.
	 *
	 * @param  array $attributes
	 * @return void
	 */
	public function __construct($attributes = [])
	{
		parent::__construct($attributes);

		$this->parent_id = $this->parent_id ?: null;
	}


	/**
	 * The "booting" method of the model.
	 *
	 * @return void
	 */
	protected static function boot()
	{
		parent::boot();

		static::saving(function ($node) {
			$node->path = $node->generatePath();
		});
	}

	/**
	 * Generate the blocks array for this page.
	 * @return array
	 */
	public function bake()
	{
		$data = [];
		$blocksByRegion = $this->blocks()
			->with('media')
			->orderBy('order')
			->get()
			->groupBy('region_name');
		$this->load('blocks.media');
		foreach ($blocksByRegion as $region => $blocks) {
			$data[$region] = [];
			foreach ($blocks as $block) {
				$block->embedMedia();
				$data[$region][] = [
					'id' => $block->id,
					'definition_name' => $block->definition_name,
					'definition_version' => $block->definition_version,
					'region_name' => $block->region_name,
					'fields' => $block->fields,
					'errors' => $block->errors
				];
			}
		}
		return $data;
	}

	/**
	 * Get the published state of the page.
	 * @return string One of 'draft', 'modified', 'published'
	 */
	public function getStatusAttribute()
	{
		$published = $this->publishedVersion();
		if($published){
			if($published->revision_id == $this->revision_id){
				return Page::STATE_PUBLISHED;
			}
			else{
				return Page::STATE_DRAFT;
			}
		}
		else{
			return Page::STATE_NEW;
		}
	}

	/************************************************************************
	 * Relations
	 ************************************************************************/

	/**
	 * The Site that this Page belongs to.
	 * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
	 */
	public function site()
	{
		return $this->belongsTo(Site::class, 'site_id');
	}

	/**
	 * The current Revision attached to this Page.
	 * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
	 */
	public function revision()
	{
		return $this->belongsTo(Revision::class, 'revision_id');
	}

	/**
	 * The Blocks linked to this Page.
	 * @return \Illuminate\Database\Eloquent\Relations\HasMany
	 */
	public function blocks()
	{
		return $this->hasMany(Block::class, 'page_id');
	}

	/************************************************************************
	 * Query Scopes
	 ************************************************************************/

	/**
	 * Restrict query to draft version of the site.
	 * @param $query
	 * @return mixed
	 */
	public function scopeDraft($query)
	{
		return $this->scopeVersion($query, self::STATE_DRAFT);
	}

	/**
	 * Restrict query to published version of the site.
	 * @param $query
	 * @return mixed
	 */
	public function scopePublished($query)
	{
		return $this->scopeVersion($query, self::STATE_PUBLISHED);
	}

	/**
	 * Restrict query to specific version of the site.
	 * @param $query
	 * @return mixed
	 */
	public function scopeVersion($query, $version)
	{
		return $query->where('version', $version);
	}

	/**
	 * Restrict query to specific site.
	 * @param $query
	 * @param $site_id
	 * @return mixed
	 */
	public function scopeforSite($query, $site_id)
	{
		return $query->where('site_id', $site_id);
	}

	/**
	 * Restrict query to page on site with specific path.
	 * @param $query
	 * @param $site_id
	 * @param $path
	 * @return mixed
	 */
	public static function scopeForSiteAndPath($query, $site_id, $path)
	{
		return $query->where('site_id', $site_id)
			->where('path', $path);
	}


	/**************************************************************************
	 * Utility Methods
	 */

	/**
	 * Get the published version of this page.
	 * @return Page The published version of this page if it exists (which may be this Page)
	 */
	public function publishedVersion()
	{
		if (Page::STATE_PUBLISHED == $this->version) {
			return $this;
		}
		return Page::published()
			->forSiteAndPath($this->site_id, $this->path)
			->first();
	}

	/**
	 * Get the next sibling page to this one.
	 * @return Page|null
	 */
	public function nextPage()
	{
		return $this->siblingsAndSelf()->get()->first(
			function ($item) {
				return $item->lft == $this->rgt + 1;
			}
		);
	}

	/**
	 * Get the previous sibling page to this one.
	 * @return Page|null
	 */
	public function previousPage()
	{
		return $this->siblingsAndSelf()->get()->first(<commit_msg>Fix to work when page whose status is queried is already the published version.<commit_after><?php

namespace App\Models;

use App\Exceptions\UnpublishedParentException;
use DB;
use Doctrine\DBAL\Version;
use Exception;
use App\Models\Definitions\Layout as LayoutDefinition;
use Baum\Node as BaumNode;
use Illuminate\Database\Eloquent\Collection;
use League\Fractal\TransformerAbstract;

/**
 * A Page represents a path in a hierarchical site structure.
 * Each page has a current revision, and each "tree" of pages is scoped by its site_id and version (draft, published, etc).
 *
 * @package App\Models
 */
class Page extends BaumNode
{
	public $table = 'pages';

	public $timestamps = false;

	protected $fillable = [
		'slug',
		'draft_id',
		'parent_id',
		'site_id',
		'version',
		'path',
		'revision_id',
		'created_by',
		'updated_by',
	];

	protected $hidden = [
		'lft',
		'rgt'
	];

	// nested set implementation has a tree for each site_id+version combination.
	protected $scoped = ['site_id', 'version'];

	// The draft state of this page.
	const STATE_NEW = 'new'; // not published
	const STATE_DRAFT = 'draft'; // modified since last published
	const STATE_DELETED = 'deleted'; // deleted since last published
	const STATE_MOVED = 'moved'; // moved since last published
	const STATE_PUBLISHED = 'published'; // not modified since last published
	const STATE_EMPTY = 'empty'; // no draft or published state.


	/**
	 * Create a new Eloquent model instance.
	 *
	 * @param  array $attributes
	 * @return void
	 */
	public function __construct($attributes = [])
	{
		parent::__construct($attributes);

		$this->parent_id = $this->parent_id ?: null;
	}


	/**
	 * The "booting" method of the model.
	 *
	 * @return void
	 */
	protected static function boot()
	{
		parent::boot();

		static::saving(function ($node) {
			$node->path = $node->generatePath();
		});
	}

	/**
	 * Generate the blocks array for this page.
	 * @return array
	 */
	public function bake()
	{
		$data = [];
		$blocksByRegion = $this->blocks()
			->with('media')
			->orderBy('order')
			->get()
			->groupBy('region_name');
		$this->load('blocks.media');
		foreach ($blocksByRegion as $region => $blocks) {
			$data[$region] = [];
			foreach ($blocks as $block) {
				$block->embedMedia();
				$data[$region][] = [
					'id' => $block->id,
					'definition_name' => $block->definition_name,
					'definition_version' => $block->definition_version,
					'region_name' => $block->region_name,
					'fields' => $block->fields,
					'errors' => $block->errors
				];
			}
		}
		return $data;
	}

	/**
	 * Get the published state of the page.
	 * @return string One of 'new', 'draft', 'published'
	 */
	public function getStatusAttribute()
	{
		if(Page::STATE_DRAFT == $this->version){
			$compare_to = $this->publishedVersion();
		}
		else {
			$compare_to = $this->draftVersion();
		}
		if($compare_to){
			if($compare_to->revision_id == $this->revision_id){
				return Page::STATE_PUBLISHED;
			}
			else{
				return Page::STATE_DRAFT;
			}
		}
		else{
			return Page::STATE_NEW;
		}
	}

	/************************************************************************
	 * Relations
	 ************************************************************************/

	/**
	 * The Site that this Page belongs to.
	 * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
	 */
	public function site()
	{
		return $this->belongsTo(Site::class, 'site_id');
	}

	/**
	 * The current Revision attached to this Page.
	 * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
	 */
	public function revision()
	{
		return $this->belongsTo(Revision::class, 'revision_id');
	}

	/**
	 * The Blocks linked to this Page.
	 * @return \Illuminate\Database\Eloquent\Relations\HasMany
	 */
	public function blocks()
	{
		return $this->hasMany(Block::class, 'page_id');
	}

	/************************************************************************
	 * Query Scopes
	 ************************************************************************/

	/**
	 * Restrict query to draft version of the site.
	 * @param $query
	 * @return mixed
	 */
	public function scopeDraft($query)
	{
		return $this->scopeVersion($query, self::STATE_DRAFT);
	}

	/**
	 * Restrict query to published version of the site.
	 * @param $query
	 * @return mixed
	 */
	public function scopePublished($query)
	{
		return $this->scopeVersion($query, self::STATE_PUBLISHED);
	}

	/**
	 * Restrict query to specific version of the site.
	 * @param $query
	 * @return mixed
	 */
	public function scopeVersion($query, $version)
	{
		return $query->where('version', $version);
	}

	/**
	 * Restrict query to specific site.
	 * @param $query
	 * @param $site_id
	 * @return mixed
	 */
	public function scopeforSite($query, $site_id)
	{
		return $query->where('site_id', $site_id);
	}

	/**
	 * Restrict query to page on site with specific path.
	 * @param $query
	 * @param $site_id
	 * @param $path
	 * @return mixed
	 */
	public static function scopeForSiteAndPath($query, $site_id, $path)
	{
		return $query->where('site_id', $site_id)
			->where('path', $path);
	}


	/**************************************************************************
	 * Utility Methods
	 */

	/**
	 * Get the published version of this page.
	 * @return Page The published version of this page if it exists (which may be this Page)
	 */
	public function publishedVersion()
	{
		if (Page::STATE_PUBLISHED == $this->version) {
			return $this;
		}
		return Page::published()
			->forSiteAndPath($this->site_id, $this->path)
			->first();
	}

	/**
	 * Get the draft version of this page.
	 * @return Page The draft version of this page if it exists (which may be this Page)
	 */
	public function draftVersion()
	{
		if (Page::STATE_DRAFT == $this->version) {
			return $this;
		}
		return Page::draft()
			->forSiteAndPath($this->site_id, $this->path)
			->first();
	}

	/**
	 * Get the next sibling page to this one.
	 * @return Page|null
	 */
	public function nextPage()
	{
		return $this->siblingsAndSelf()->get()->first(
			function ($item) {
				return $item->lft == $this->rgt + 1;
			}
		);
	}

	/**
	 * Get the previous sibling page to this one.
	 * @return Page|null
	 */
	public function previousPage()
	{
		return $this->siblingsAndSelf()->get()->first(
{'fraction_non_alphanumeric': 0.20026591324580356, 'fraction_numerical': 0.00016619577862722287, 'mean_word_length': 3.661115414407436, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 108, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, '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': '5281918', 'n_tokens_mistral': 4212, 'n_tokens_neox': 3688, 'n_words': 1005}