<commit_before><?php

namespace SilverStripe\CMS\Model;

use Page;
use SilverStripe\Core\Convert;
use SilverStripe\Dev\Deprecation;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\LiteralField;
use SilverStripe\Forms\ReadonlyTransformation;
use SilverStripe\Forms\TreeDropdownField;
use SilverStripe\ORM\DataObject;
use SilverStripe\ORM\ValidationResult;
use SilverStripe\Security\Member;
use SilverStripe\Versioned\Versioned;
use SilverStripe\View\HTML;

/**
 * Virtual Page creates an instance of a  page, with the same fields that the original page had, but readonly.
 * This allows you can have a page in mulitple places in the site structure, with different children without
 * duplicating the content.
 *
 * Note: This Only duplicates $db fields and not the $has_one etc..
 *
 * @method SiteTree CopyContentFrom()
 * @property int $CopyContentFromID
 */
class VirtualPage extends Page
{
    private static $description = 'Displays the content of another page';

    private static $icon_class = 'font-icon-p-virtual';

    public static $virtualFields;

    /**
     * @var array Define fields that are not virtual - the virtual page must define these fields themselves.
     * Note that anything in {@link self::config()->initially_copied_fields} is implicitly included in this list.
     */
    private static $non_virtual_fields = [
        "ID",
        "ClassName",
        "ObsoleteClassName",
        "SecurityTypeID",
        "OwnerID",
        "ParentID",
        "URLSegment",
        "Sort",
        "Status",
        'ShowInMenus',
        // 'Locale'
        'ShowInSearch',
        'Version',
        "Embargo",
        "Expiry",
        "CanViewType",
        "CanEditType",
        "CopyContentFromID",
        "HasBrokenLink",
    ];

    /**
     * @var array Define fields that are initially copied to virtual pages but left modifiable after that.
     */
    private static $initially_copied_fields = [
        'ShowInMenus',
        'ShowInSearch',
        'URLSegment',
    ];

    private static $has_one = [
        "CopyContentFrom" => SiteTree::class,
    ];

    private static $owns = [
        "CopyContentFrom",
    ];

    private static $db = [
        "VersionID" => "Int",
    ];

    private static $table_name = 'VirtualPage';

    /**
     * Generates the array of fields required for the page type.
     *
     * @return array
     */
    public function getVirtualFields()
    {
        // Check if copied page exists
        $record = $this->CopyContentFrom();
        if (!$record || !$record->exists()) {
            return [];
        }

        // Diff db with non-virtual fields
        $fields = array_keys(static::getSchema()->fieldSpecs($record));
        $nonVirtualFields = $this->getNonVirtualisedFields();
        return array_diff($fields, $nonVirtualFields);
    }

    /**
     * List of fields or properties to never virtualise
     *
     * @return array
     */
    public function getNonVirtualisedFields()
    {
        $config = self::config();
        return array_merge(
            $config->get('non_virtual_fields'),
            $config->get('initially_copied_fields')
        );
    }

    public function setCopyContentFromID($val)
    {
        // Sanity check to prevent pages virtualising other virtual pages
        if ($val && DataObject::get_by_id(SiteTree::class, $val) instanceof VirtualPage) {
            $val = 0;
        }
        return $this->setField("CopyContentFromID", $val);
    }

    public function ContentSource()
    {
        $copied = $this->CopyContentFrom();
        if ($copied && $copied->exists()) {
            return $copied;
        }
        return $this;
    }

    /**
     * For VirtualPage, add a canonical link tag linking to the original page
     * See TRAC #6828 & http://support.google.com/webmasters/bin/answer.py?hl=en&answer=139394
     *
     * @param boolean $includeTitle Show default <title>-tag, set to false for custom templating
     * @return string The XHTML metatags
     */
    public function MetaTags($includeTitle = true)
    {
        $tags = parent::MetaTags($includeTitle);
        $copied = $this->CopyContentFrom();
        if ($copied && $copied->exists()) {
            $tags .= HTML::createTag('link', [
                'rel' => 'canonical',
                'href' => $copied->Link()
            ]);
            $tags .= "\n";
        }
        return $tags;
    }

    public function allowedChildren()
    {
        $copy = $this->CopyContentFrom();
        if ($copy && $copy->exists()) {
            return $copy->allowedChildren();
        }
        return [];
    }

    public function syncLinkTracking()
    {
        if ($this->CopyContentFromID) {
            $this->HasBrokenLink = Versioned::get_by_stage(SiteTree::class, Versioned::DRAFT)
                ->filter('ID', $this->CopyContentFromID)
                ->count() === 0;
        } else {
            $this->HasBrokenLink = true;
        }
    }<commit_msg>UPDATE generate canonical via MetaComponents<commit_after><?php

namespace SilverStripe\CMS\Model;

use Page;
use SilverStripe\Core\Convert;
use SilverStripe\Dev\Deprecation;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\LiteralField;
use SilverStripe\Forms\ReadonlyTransformation;
use SilverStripe\Forms\TreeDropdownField;
use SilverStripe\ORM\DataObject;
use SilverStripe\ORM\ValidationResult;
use SilverStripe\Security\Member;
use SilverStripe\Versioned\Versioned;
use SilverStripe\View\HTML;

/**
 * Virtual Page creates an instance of a  page, with the same fields that the original page had, but readonly.
 * This allows you can have a page in mulitple places in the site structure, with different children without
 * duplicating the content.
 *
 * Note: This Only duplicates $db fields and not the $has_one etc..
 *
 * @method SiteTree CopyContentFrom()
 * @property int $CopyContentFromID
 */
class VirtualPage extends Page
{
    private static $description = 'Displays the content of another page';

    private static $icon_class = 'font-icon-p-virtual';

    public static $virtualFields;

    /**
     * @var array Define fields that are not virtual - the virtual page must define these fields themselves.
     * Note that anything in {@link self::config()->initially_copied_fields} is implicitly included in this list.
     */
    private static $non_virtual_fields = [
        "ID",
        "ClassName",
        "ObsoleteClassName",
        "SecurityTypeID",
        "OwnerID",
        "ParentID",
        "URLSegment",
        "Sort",
        "Status",
        'ShowInMenus',
        // 'Locale'
        'ShowInSearch',
        'Version',
        "Embargo",
        "Expiry",
        "CanViewType",
        "CanEditType",
        "CopyContentFromID",
        "HasBrokenLink",
    ];

    /**
     * @var array Define fields that are initially copied to virtual pages but left modifiable after that.
     */
    private static $initially_copied_fields = [
        'ShowInMenus',
        'ShowInSearch',
        'URLSegment',
    ];

    private static $has_one = [
        "CopyContentFrom" => SiteTree::class,
    ];

    private static $owns = [
        "CopyContentFrom",
    ];

    private static $db = [
        "VersionID" => "Int",
    ];

    private static $table_name = 'VirtualPage';

    /**
     * Generates the array of fields required for the page type.
     *
     * @return array
     */
    public function getVirtualFields()
    {
        // Check if copied page exists
        $record = $this->CopyContentFrom();
        if (!$record || !$record->exists()) {
            return [];
        }

        // Diff db with non-virtual fields
        $fields = array_keys(static::getSchema()->fieldSpecs($record));
        $nonVirtualFields = $this->getNonVirtualisedFields();
        return array_diff($fields, $nonVirtualFields);
    }

    /**
     * List of fields or properties to never virtualise
     *
     * @return array
     */
    public function getNonVirtualisedFields()
    {
        $config = self::config();
        return array_merge(
            $config->get('non_virtual_fields'),
            $config->get('initially_copied_fields')
        );
    }

    public function setCopyContentFromID($val)
    {
        // Sanity check to prevent pages virtualising other virtual pages
        if ($val && DataObject::get_by_id(SiteTree::class, $val) instanceof VirtualPage) {
            $val = 0;
        }
        return $this->setField("CopyContentFromID", $val);
    }

    public function ContentSource()
    {
        $copied = $this->CopyContentFrom();
        if ($copied && $copied->exists()) {
            return $copied;
        }
        return $this;
    }

    /**
     * @return array
     */
    public function MetaComponents()
    {
        $tags = parent::MetaComponents();

        $copied = $this->CopyContentFrom();
        if ($copied && $copied->exists()) {
            $tags['canonical'] = [
                'attributes' => [
                    'rel' => 'canonical',
                    'content' => $copied->AbsoluteLink(),
                ],
            ];
        }

        return $tags;
    }

    public function allowedChildren()
    {
        $copy = $this->CopyContentFrom();
        if ($copy && $copy->exists()) {
            return $copy->allowedChildren();
        }
        return [];
    }

    public function syncLinkTracking()
    {
        if ($this->CopyContentFromID) {
            $this->HasBrokenLink = Versioned::get_by_stage(SiteTree::class, Versioned::DRAFT)
                ->filter('ID', $this->CopyContentFromID)
                ->count() === 0;
        } else {
            $this->HasBrokenLink = true;
        }
    }
{'fraction_non_alphanumeric': 0.11788953009068426, 'fraction_numerical': 0.0014427040395713108, 'mean_word_length': 2.27318718381113, 'pattern_counts': {'":': 0, '<': 6, '<?xml version=': 0, '>': 57, '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': '7118754', 'n_tokens_mistral': 2765, 'n_tokens_neox': 2705, 'n_words': 702}