<commit_before><?php
/*
 * Copyright 2015 <NAME> <http://jacksleight.com/>
 * This source file is subject to the MIT license that is bundled with this package in the file LICENCE.md. 
 */

namespace Chalk\Core;

use Chalk\App as Chalk;
use Chalk\Backend;
use Chalk\Core\Behaviour\Loggable\Listener as LoggableListener;
use Chalk\Core\Behaviour\Publishable\Listener as PublishableListener;
use Chalk\Core\Behaviour\Searchable\Listener as SearchableListener;
use Chalk\Core\Behaviour\Trackable\Listener as TrackableListener;
use Chalk\Core\Behaviour\Versionable\Listener as VersionableListener;
use Chalk\Core\File\Listener as FileListener;
use Chalk\Core\Parser\Plugin\Backend as PluginBackend;
use Chalk\Core\Parser\Plugin\Frontend as PluginFrontend;
use Chalk\Core\Parser\Plugin\StripEmpty;
use Chalk\Core\Structure\Node\Listener as StructureNodeListener;
use Chalk\Event;
use Chalk\Frontend;
use Chalk\InfoList;
use Chalk\Module as ChalkModule;
use Chalk\Parser;
use Chalk\Repository;
use Closure;
use Coast\Request;
use Coast\Response;
use Coast\Router;
use DOMDocument;
use DOMXPath;

class Module extends ChalkModule
{
    public function __construct()
    {
        parent::__construct('core');
    }
    
    public function init()
    {
        $this
            ->entityDir($this->name())
            ->entityListener($this->name('file'), new FileListener())
            ->entityListener($this->name('structure_node'), new StructureNodeListener())
            ->entityListener($this->name('publishable'), new PublishableListener())
            ->entityListener($this->name('searchable'), new SearchableListener())
            // ->entityListener($this->name('loggable'), new LoggableListener())
            // ->entityListener($this->name('versionable'), new VersionableListener())
            ->entityListener($this->name('trackable'), $trackable = new TrackableListener());
    }
    
    public function frontendInit()
    {
        $this
            ->frontendControllerAll($this->name())
            ->frontendControllerNspace($this->name())
            ->frontendViewDir($this->name());

        $this
            ->frontendParserPlugin($this->name('frontend'), new PluginFrontend())
            ->frontendParserPlugin($this->name('stripEmpty'), new StripEmpty([
                'tags' => ['p'],
            ]));

        $this
            ->frontendUrlResolver($this->name('structure_node'), function($node, $info) {
                try {
                    return $this->frontend->url
                        ->route([], $this->name("structure_node_{$node['id']}"), true);   
                } catch (\Coast\Router\Exception $e) {}             
            })
            ->frontendUrlResolver($this->name('content'), function($content, $info) {
                try {
                    return $this->frontend->url
                        ->route([], $this->name("content_{$content['id']}"), true);
                } catch (\Coast\Router\Exception $e) {}
            })
            ->frontendUrlResolver($this->name('url'), function($url, $info) {
                return $url['url'];
            })
            ->frontendUrlResolver($this->name('file'), function($file, $info) {
                if (is_array($file)) {
                    // @todo Remove this once File works with array hydration
                    $file = $this->em($this->name('file'))->id($file['id']);
                }
                return $this->frontend->url
                    ->file($file['file']);
            });

        if ($this->app->isHttp()) {
            $this->frontendInitDomain();
            $this->frontendInitNodes();
        }
    }

    public function frontendInitDomain()
    {
        $domain = $this->em($this->name('domain'))->id(1, [], [
            'hydrate' => Repository::HYDRATE_ARRAY,
        ]);
        
        $this->frontend->domain = $domain;
        $this->frontend->root   = $domain['structures'][0]['nodes'][0];
        $this->frontend->home   = $domain['structures'][0]['nodes'][0]['content'];
        
        $structures = [];
        foreach ($domain['structures'] as $structure) {
            $structure['root']              = $structure['nodes'][0];
            $structures[$structure['id']]   = $structure;
            $structures[$structure['slug']] = $structure;
        }
        $this->frontend->structures = $structures;
    }

    public function frontendInitNodes()
    {
        $conn  = $this->em->getConnection();
        $nodes = $conn->query("
            SELECT n.id,
                n.sort, n.left, n.right, n.depth,
                n.name, n.slug, n.path,
                n.structureId,
                n.parentId,
                c.id AS content_id,
                c.type AS content_type,
                c.data AS content_data
            FROM core_structure_node AS n
                INNER JOIN core_structure AS s ON s.id = n.structureId
                INNER JOIN core_domain__core_structure AS d ON d.core_structureId = s.id
                INNER JOIN core_content AS c ON c.id = n.contentId
            WHERE d.core_domainId = {$this->frontend->domain['id']}
        ")->fetchAll();

        $nodeMap = [];
        foreach ($nodes as $node) {
            $content = [
                'id'   => $node['content_id'],
                'type' => $node['content_type'],
                'data' => json_decode($node['content_data'], true),
            ];
            if (!isset($content['id'])) {
                continue;
            }
            if (isset($content['data']['delegate'])) {
                $delegate = $content['data']['delegate'] + [
                    'name'   => null,
                    'params' => [],
                ];
                $info   = Chalk::info($delegate['name']);
                $name   = 'content';
                $params = $delegate['params'];
            } else {
                $info   = Chalk::info($node['content_type']);
                $name   = $info->local->name;
                $params = [];
            }
            $module = $this->app->module($info->module->name);
            if (!method_exists($module, 'core_frontendInitNode')) {
                throw new \Chalk\Exception("Module '{$info->module->name}' does not implment 'core_frontendInitNode'");
            }
            $params = [
                'group'   => $module->name(),
                'node'    => $node,
                'content' => $content,
                $name     => $content['id'],
            ] + $params;
            $primary = $module->core_frontendInitNode(
                $info->local->name,
                $node,
                $content,
                $params
            );
            if (!$primary) {
                throw new \Chalk\Exception("No primary route provided for '{$info->name}' on node '{$node['id']}'");
            }
            $this
                ->frontendRouteAlias(
                    $this->name("content_{$content['id']}"),
                    $primary
                )
                ->frontendRouteAlias(
                    $this->name("structure_node_{$node['id']}"),
                    $primary
                );
            $nodeMap[$node['id']] = $node;
        }
        $this->nodeMap = $nodeMap;
    }
    
    public function backendInit()
    {
        $this
            ->backendControllerAll($this->name())
            ->backendControllerNspace($this->name())
            ->backendViewDir($this->name());

        $this
            ->backendParserPlugin($this->name('backend'), new PluginBackend());

        $this
            ->backendRoute(
                $this->name('index'),
                Router::METHOD_ALL,
                "{controller}?/{action}?/{id}?", [
                    'controller' => 'index',
                    'action'     => 'index',
                    'id'         => null,
                ])
            ->backendRoute(
                $this->name('about'),<commit_msg>Fix node map variable.<commit_after><?php
/*
 * Copyright 2015 <NAME> <http://jacksleight.com/>
 * This source file is subject to the MIT license that is bundled with this package in the file LICENCE.md. 
 */

namespace Chalk\Core;

use Chalk\App as Chalk;
use Chalk\Backend;
use Chalk\Core\Behaviour\Loggable\Listener as LoggableListener;
use Chalk\Core\Behaviour\Publishable\Listener as PublishableListener;
use Chalk\Core\Behaviour\Searchable\Listener as SearchableListener;
use Chalk\Core\Behaviour\Trackable\Listener as TrackableListener;
use Chalk\Core\Behaviour\Versionable\Listener as VersionableListener;
use Chalk\Core\File\Listener as FileListener;
use Chalk\Core\Parser\Plugin\Backend as PluginBackend;
use Chalk\Core\Parser\Plugin\Frontend as PluginFrontend;
use Chalk\Core\Parser\Plugin\StripEmpty;
use Chalk\Core\Structure\Node\Listener as StructureNodeListener;
use Chalk\Event;
use Chalk\Frontend;
use Chalk\InfoList;
use Chalk\Module as ChalkModule;
use Chalk\Parser;
use Chalk\Repository;
use Closure;
use Coast\Request;
use Coast\Response;
use Coast\Router;
use DOMDocument;
use DOMXPath;

class Module extends ChalkModule
{
    public function __construct()
    {
        parent::__construct('core');
    }
    
    public function init()
    {
        $this
            ->entityDir($this->name())
            ->entityListener($this->name('file'), new FileListener())
            ->entityListener($this->name('structure_node'), new StructureNodeListener())
            ->entityListener($this->name('publishable'), new PublishableListener())
            ->entityListener($this->name('searchable'), new SearchableListener())
            // ->entityListener($this->name('loggable'), new LoggableListener())
            // ->entityListener($this->name('versionable'), new VersionableListener())
            ->entityListener($this->name('trackable'), $trackable = new TrackableListener());
    }
    
    public function frontendInit()
    {
        $this
            ->frontendControllerAll($this->name())
            ->frontendControllerNspace($this->name())
            ->frontendViewDir($this->name());

        $this
            ->frontendParserPlugin($this->name('frontend'), new PluginFrontend())
            ->frontendParserPlugin($this->name('stripEmpty'), new StripEmpty([
                'tags' => ['p'],
            ]));

        $this
            ->frontendUrlResolver($this->name('structure_node'), function($node, $info) {
                try {
                    return $this->frontend->url
                        ->route([], $this->name("structure_node_{$node['id']}"), true);   
                } catch (\Coast\Router\Exception $e) {}             
            })
            ->frontendUrlResolver($this->name('content'), function($content, $info) {
                try {
                    return $this->frontend->url
                        ->route([], $this->name("content_{$content['id']}"), true);
                } catch (\Coast\Router\Exception $e) {}
            })
            ->frontendUrlResolver($this->name('url'), function($url, $info) {
                return $url['url'];
            })
            ->frontendUrlResolver($this->name('file'), function($file, $info) {
                if (is_array($file)) {
                    // @todo Remove this once File works with array hydration
                    $file = $this->em($this->name('file'))->id($file['id']);
                }
                return $this->frontend->url
                    ->file($file['file']);
            });

        if ($this->app->isHttp()) {
            $this->frontendInitDomain();
            $this->frontendInitNodes();
        }
    }

    public function frontendInitDomain()
    {
        $domain = $this->em($this->name('domain'))->id(1, [], [
            'hydrate' => Repository::HYDRATE_ARRAY,
        ]);
        
        $this->frontend->domain = $domain;
        $this->frontend->root   = $domain['structures'][0]['nodes'][0];
        $this->frontend->home   = $domain['structures'][0]['nodes'][0]['content'];
        
        $structures = [];
        foreach ($domain['structures'] as $structure) {
            $structure['root']              = $structure['nodes'][0];
            $structures[$structure['id']]   = $structure;
            $structures[$structure['slug']] = $structure;
        }
        $this->frontend->structures = $structures;
    }

    public function frontendInitNodes()
    {
        $conn  = $this->em->getConnection();
        $nodes = $conn->query("
            SELECT n.id,
                n.sort, n.left, n.right, n.depth,
                n.name, n.slug, n.path,
                n.structureId,
                n.parentId,
                c.id AS content_id,
                c.type AS content_type,
                c.data AS content_data
            FROM core_structure_node AS n
                INNER JOIN core_structure AS s ON s.id = n.structureId
                INNER JOIN core_domain__core_structure AS d ON d.core_structureId = s.id
                INNER JOIN core_content AS c ON c.id = n.contentId
            WHERE d.core_domainId = {$this->frontend->domain['id']}
        ")->fetchAll();

        $nodeMap = [];
        foreach ($nodes as $node) {
            $content = [
                'id'   => $node['content_id'],
                'type' => $node['content_type'],
                'data' => json_decode($node['content_data'], true),
            ];
            if (!isset($content['id'])) {
                continue;
            }
            if (isset($content['data']['delegate'])) {
                $delegate = $content['data']['delegate'] + [
                    'name'   => null,
                    'params' => [],
                ];
                $info   = Chalk::info($delegate['name']);
                $name   = 'content';
                $params = $delegate['params'];
            } else {
                $info   = Chalk::info($node['content_type']);
                $name   = $info->local->name;
                $params = [];
            }
            $module = $this->app->module($info->module->name);
            if (!method_exists($module, 'core_frontendInitNode')) {
                throw new \Chalk\Exception("Module '{$info->module->name}' does not implment 'core_frontendInitNode'");
            }
            $params = [
                'group'   => $module->name(),
                'node'    => $node,
                'content' => $content,
                $name     => $content['id'],
            ] + $params;
            $primary = $module->core_frontendInitNode(
                $info->local->name,
                $node,
                $content,
                $params
            );
            if (!$primary) {
                throw new \Chalk\Exception("No primary route provided for '{$info->name}' on node '{$node['id']}'");
            }
            $this
                ->frontendRouteAlias(
                    $this->name("content_{$content['id']}"),
                    $primary
                )
                ->frontendRouteAlias(
                    $this->name("structure_node_{$node['id']}"),
                    $primary
                );
            $nodeMap[$node['id']] = $node;
        }
        $this->frontend->nodeMap = $nodeMap;
    }
    
    public function backendInit()
    {
        $this
            ->backendControllerAll($this->name())
            ->backendControllerNspace($this->name())
            ->backendViewDir($this->name());

        $this
            ->backendParserPlugin($this->name('backend'), new PluginBackend());

        $this
            ->backendRoute(
                $this->name('index'),
                Router::METHOD_ALL,
                "{controller}?/{action}?/{id}?", [
                    'controller' => 'index',
                    'action'     => 'index',
                    'id'         => null,
                ])
            ->backendRoute(
                $this->name('about'),
{'fraction_non_alphanumeric': 0.1525743383416106, 'fraction_numerical': 0.0012573081033507261, 'mean_word_length': 1.7493950916004148, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 234, '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': '5496077', 'n_tokens_mistral': 4371, 'n_tokens_neox': 4180, 'n_words': 796}