Commit af08304d authored by Dominique Feyer's avatar Dominique Feyer
Browse files

[TASK] Initial commit

parents
Loading
Loading
Loading
Loading
+156 −0
Original line number Diff line number Diff line
<?php
namespace Ttree\Neos\Sitemap\Command;

use Tackk\Cartographer\ChangeFrequency;
use TYPO3\Eel\FlowQuery\FlowQuery;
use TYPO3\Flow\Annotations as Flow;
use TYPO3\Flow\Cli\CommandController;
use TYPO3\Flow\Http\Request;
use TYPO3\Flow\Http\Response;
use TYPO3\Flow\Http\Uri;
use TYPO3\Flow\Mvc\ActionRequest;
use TYPO3\Flow\Mvc\Controller\Arguments;
use TYPO3\Flow\Mvc\Controller\ControllerContext;
use TYPO3\Flow\Mvc\Routing\UriBuilder;
use TYPO3\Flow\Utility\Files;
use TYPO3\Neos\Domain\Repository\SiteRepository;
use TYPO3\Neos\Service\LinkingService;
use TYPO3\TYPO3CR\Domain\Model\NodeInterface;
use TYPO3\TYPO3CR\Domain\Service\ContextFactoryInterface;

class SitemapCommandController extends CommandController {

    /**
     * @var ContextFactoryInterface
     * @Flow\Inject
     */
    protected $contextFactory;

    /**
     * @var SiteRepository
     * @Flow\Inject
     */
    protected $siteRepository;

    /**
     * @Flow\Inject
     * @var LinkingService
     */
    protected $linkingService;

    /**
     * @Flow\Inject
     * @var UriBuilder
     */
    protected $uriBuilder;

    /**
     * @Flow\InjectConfiguration("presets")
     * @var array
     */
    protected $presets;

    /**
     * @param string $siteNodeName
     * @param string $baseUrl
     * @param string $preset
     */
    public function generateCommand($siteNodeName, $baseUrl, $preset = 'default') {
        if (!isset($this->presets[$preset])) {
            $this->outputLine('Preset "%s" not found ...', [$preset]);
            $this->sendAndExit(1);
        }
        $preset = $this->presets[$preset];
        $processedUri = [];
        $sitemap = new \Tackk\Cartographer\Sitemap();

        $context = $this->createContext('live', $siteNodeName);
        $controllerContext = $this->createControllerContext($baseUrl);

        foreach ($preset['include'] as $nodeType => $nodeTypeStatus) {
            if ($nodeTypeStatus !== TRUE) {
                continue;
            }
            $flowQuery = new FlowQuery(array($context->getRootNode()));
            /** @var NodeInterface $node */
            foreach ($flowQuery->find(sprintf('[instanceof %s]', $nodeType)) as $node) {
                if ($this->needToSkipNode($preset, $node)) {
                    continue;
                }
                if (trim($node->getProperty('uriPathSegment')) === '') {
                    $this->outputLine('Skip "%s" (%s), uriPathSegment empty', [$node->getLabel(), $node->getPath()]);
                    continue;
                }
                $uri = $this->linkingService->createNodeUri($controllerContext, $node, NULL, 'html', TRUE);
                $hash = md5($uri);
                if (isset($processedUri[$hash])) {
                    $this->outputLine('Skip "%s" (%s), duplicate URI (%s)', [$node->getLabel(), $node->getPath(), $uri]);
                    continue;
                }
                $lastPublicationDateTime = $node->getNodeData()->getLastPublicationDateTime() ?: $node->getNodeData()->getLastModificationDateTime();
                $sitemap->add($uri, $lastPublicationDateTime ? $lastPublicationDateTime->format('Y-m-d') : null, ChangeFrequency::WEEKLY, 1.0);
                $processedUri[$hash] = TRUE;
            }
        }

        $pathAndFilename = FLOW_PATH_DATA . '/Persistent/Sitemaps/sitemap.xml';
        Files::createDirectoryRecursively(dirname($pathAndFilename));
        file_put_contents($pathAndFilename, (string)$sitemap);
    }

    /**
     * @param array $preset
     * @param NodeInterface $node
     * @return boolean
     */
    protected function needToSkipNode(array $preset, NodeInterface $node) {
        if (isset($preset['skip']) && is_array($preset['skip'])) {
            foreach ($preset['skip'] as $nodeType => $nodeTypeStatus) {
                if ($nodeTypeStatus !== TRUE) {
                    continue;
                }
                if ($node->getNodeType()->isOfType($nodeType) === TRUE) {
                    return TRUE;
                }
            }
        }
        return FALSE;
    }

    /**
     * @param string $baseUrl
     * @return ControllerContext
     */
    protected function createControllerContext($baseUrl) {
        $httpRequest = Request::create(new Uri($baseUrl));
        $response = new Response();
        $arguments = new Arguments([]);
        return new ControllerContext(new ActionRequest($httpRequest), $response, $arguments, $this->uriBuilder);
    }

    /**
     * Creates a content context for given workspace and language identifiers
     *
     * @param string $workspaceName
     * @param string $siteNodeName
     * @param array $languageIdentifiers
     * @return \TYPO3\TYPO3CR\Domain\Service\Context
     */
    protected function createContext($workspaceName, $siteNodeName, array $languageIdentifiers = NULL) {
        $site = $this->siteRepository->findOneByNodeName($siteNodeName);
        $contextProperties = array(
            'workspaceName' => $workspaceName,
            'currentSite' => $site,
            'invisibleContentShown' => TRUE,
            'inaccessibleContentShown' => TRUE
        );
        if ($languageIdentifiers !== NULL) {
            $contextProperties = array_merge($contextProperties, array(
                'dimensions' => array('language' => $languageIdentifiers)
            ));
        }
        return $this->contextFactory->create($contextProperties);
    }


}
 No newline at end of file
+17 −0
Original line number Diff line number Diff line
Ttree:
  Neos:
    Sitemap:
      presets:
        default:
          include:
            'TYPO3.Neos:Page': TRUE
          skip:
            'TYPO3.Neos:Shortcut': TRUE
          type: 'single'
        architectesCh:
          include:
            'Ttree.ArchitectesCh:BaseReport': TRUE
            'Ttree.ArchitectesCh:EntreprisePremium': TRUE
          skip:
            'TYPO3.Neos:Shortcut': TRUE
          type: 'multiple'
 No newline at end of file

composer.json

0 → 100644
+14 −0
Original line number Diff line number Diff line
{
  "name": "ttree/neos-sitemap",
  "type": "typo3-flow-package",
  "description": "Add description here",
  "require": {
    "typo3/neos": "*",
    "tackk/cartographer": "^1.1"
  },
  "autoload": {
    "psr-4": {
      "Ttree\\Neos\\Sitemap\\": "Classes"
    }
  }
}
 No newline at end of file