Skip to content

Commit

Permalink
Merge pull request #132 from sitegeist/feature/advancedPropEditors
Browse files Browse the repository at this point in the history
Advanced Prop Editors
  • Loading branch information
mficzel authored Jan 28, 2021
2 parents 7cda80e + f2037d9 commit 3612c3b
Show file tree
Hide file tree
Showing 53 changed files with 2,889 additions and 124 deletions.
50 changes: 23 additions & 27 deletions Classes/Controller/ApiController.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,11 @@
use Neos\Flow\Annotations as Flow;
use Neos\Flow\Mvc\Controller\ActionController;
use Neos\Flow\ResourceManagement\ResourceManager;
use Sitegeist\Monocle\Domain\Fusion\PrototypeRepository;
use Sitegeist\Monocle\Fusion\FusionService;
use Sitegeist\Monocle\Fusion\FusionView;
use Sitegeist\Monocle\Fusion\ReverseFusionParser;
use Sitegeist\Monocle\Service\PackageKeyTrait;
use Symfony\Component\Yaml\Yaml;
use Sitegeist\Monocle\Service\ConfigurationService;
use Sitegeist\Monocle\Domain\PrototypeDetails\PrototypeDetailsFactory;

/**
* Class ApiController
Expand Down Expand Up @@ -60,6 +59,18 @@ class ApiController extends ActionController
*/
protected $configurationService;

/**
* @Flow\Inject
* @var PrototypeRepository
*/
protected $prototypeRepository;

/**
* @Flow\Inject
* @var PrototypeDetailsFactory
*/
protected $prototypeDetailsFactory;

/**
* Get all configurations for this site package
*
Expand Down Expand Up @@ -93,30 +104,15 @@ public function configurationAction($sitePackageKey = null)
*/
public function prototypeDetailsAction($sitePackageKey, $prototypeName)
{
$sitePackageKey = $sitePackageKey ?: $this->getDefaultSitePackageKey();

$prototypePreviewRenderPath = FusionService::RENDERPATH_DISCRIMINATOR . str_replace(['.', ':'], ['_', '__'], $prototypeName);

// render html
$fusionView = new FusionView();
$fusionView->setControllerContext($this->getControllerContext());
$fusionView->setFusionPath($prototypePreviewRenderPath);
$fusionView->setPackageKey($sitePackageKey);

// render fusion source
$fusionObjectTree = $this->fusionService->getMergedFusionObjectTreeForSitePackage($sitePackageKey);
$fusionAst = $fusionObjectTree['__prototypes'][$prototypeName];
$fusionCode = ReverseFusionParser::restorePrototypeCode($prototypeName, $fusionAst);

$result = [
'prototypeName' => $prototypeName,
'renderedCode' => $fusionCode,
'parsedCode' => Yaml::dump($fusionAst, 99),
'fusionAst' => $fusionAst,
'anatomy' => $this->fusionService->getAnatomicalPrototypeTreeFromAstExcerpt($fusionAst)
];

$this->view->assign('value', $result);
$prototype = $this->prototypeRepository
->findOneByPrototypeNameInSitePackage(
$prototypeName,
$sitePackageKey
);
$prototypeDetails = $this->prototypeDetailsFactory
->forPrototype($prototype);

$this->view->assign('value', $prototypeDetails);
}

/**
Expand Down
141 changes: 141 additions & 0 deletions Classes/Domain/Fusion/Prototype.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
<?php declare(strict_types=1);
namespace Sitegeist\Monocle\Domain\Fusion;

/**
* This file is part of the Sitegeist.Monocle package
*
* (c) 2020
* Martin Ficzel <ficzel@sitegeist.de>
* Wilhelm Behncke <behncke@sitegeist.de>
*
* This package is Open Source Software. For the full copyright and license
* information, please view the LICENSE file which was distributed with this
* source code.
*/

use Neos\Flow\Annotations as Flow;
use Neos\Utility\Arrays;
use Neos\Fusion\Core\Runtime as FusionRuntime;

/**
* @Flow\Proxy(false)
*/
final class Prototype
{
/**
* @var PrototypeName
*/
private $name;

/**
* @var array<string,mixed>
*/
private $ast;

/**
* @var FusionRuntime
*/
private $runtime;

/**
* @param PrototypeName $name
* @param array<string,mixed> $ast
* @param FusionRuntime $runtime
*/
public function __construct(
PrototypeName $name,
array $ast,
FusionRuntime $runtime
) {
$this->name = $name;
$this->ast = $ast;
$this->runtime = $runtime;
}

/**
* @return PrototypeName
*/
public function getName(): PrototypeName
{
return $this->name;
}

/**
* @return array
*/
public function getAst(): array
{
return $this->ast;
}

/**
* @return boolean
*/
public function isComponent(): bool
{
return $this->extends(
PrototypeName::fromString('Neos.Fusion:Component')
);
}

/**
* @param PrototypeName $ancestorPrototypeName
* @return boolean
*/
public function extends(PrototypeName $ancestorPrototypeName): bool
{
if (isset($this->ast['__prototypeChain'])) {
return in_array(
(string) $ancestorPrototypeName,
$this->ast['__prototypeChain']
);
}

return false;
}

/**
* @param null|string $path
* @return array|string[]
*/
public function getKeys(?string $path = null): array
{
if ($path !== null) {
$ast = Arrays::getValueByPath($this->ast, $path);
if (!is_array($ast)) {
$ast = [];
}
} else {
$ast = $this->ast;
}

return array_filter(array_keys($ast), function (string $key): bool {
return substr($key, 0, 2) !== '__';
});
}

/**
* @param string $path
* @param array $context
* @return mixed
*/
public function evaluate(string $path, array $context = [])
{
if ($path[0] !== '/') {
throw new \InvalidArgumentException(
'$path must start with "/".'
);
}

$currentContext = $this->runtime->getCurrentContext();
$this->runtime->pushContextArray(array_merge($currentContext ?: [], $context));

$result = $this->runtime->evaluate(
sprintf('/<%s>%s', $this->name, $path)
);

$this->runtime->popContext();

return $result;
}
}
60 changes: 60 additions & 0 deletions Classes/Domain/Fusion/PrototypeName.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php declare(strict_types=1);
namespace Sitegeist\Monocle\Domain\Fusion;

/**
* This file is part of the Sitegeist.Monocle package
*
* (c) 2020
* Martin Ficzel <ficzel@sitegeist.de>
* Wilhelm Behncke <behncke@sitegeist.de>
*
* This package is Open Source Software. For the full copyright and license
* information, please view the LICENSE file which was distributed with this
* source code.
*/

use Neos\Flow\Annotations as Flow;

/**
* @Flow\Proxy(false)
*/
final class PrototypeName implements \JsonSerializable
{
/**
* @var string
*/
private $value;

/**
* @param string $value
*/
private function __construct(string $value)
{
$this->value = $value;
}

/**
* @param string $string
* @return self
*/
public static function fromString(string $string): self
{
return new self($string);
}

/**
* @return string
*/
public function jsonSerialize()
{
return $this->value;
}

/**
* @return string
*/
public function __toString(): string
{
return $this->value;
}
}
57 changes: 57 additions & 0 deletions Classes/Domain/Fusion/PrototypeRepository.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?php declare(strict_types=1);
namespace Sitegeist\Monocle\Domain\Fusion;

/**
* This file is part of the Sitegeist.Monocle package
*
* (c) 2020
* Martin Ficzel <ficzel@sitegeist.de>
* Wilhelm Behncke <behncke@sitegeist.de>
*
* This package is Open Source Software. For the full copyright and license
* information, please view the LICENSE file which was distributed with this
* source code.
*/

use Neos\Flow\Annotations as Flow;
use Neos\Fusion\Core\Runtime as FusionRuntime;
use Neos\Fusion\Core\RuntimeFactory as FusionRuntimeFactory;
use Sitegeist\Monocle\Fusion\FusionService;

/**
* @Flow\Scope("singleton")
*/
final class PrototypeRepository
{
/**
* @Flow\Inject
* @var FusionRuntimeFactory
*/
protected $fusionRuntimeFactory;

/**
* @Flow\Inject
* @var FusionService
*/
protected $fusionService;

public function findOneByPrototypeNameInSitePackage(
string $prototypeName,
string $sitePackageKey
): ?Prototype {
$fusionObjectTree = $this->fusionService->getMergedFusionObjectTreeForSitePackage($sitePackageKey);

if (isset($fusionObjectTree['__prototypes'][$prototypeName])) {
$fusionAst = $fusionObjectTree['__prototypes'][$prototypeName];
$fusionRuntime = $this->fusionRuntimeFactory->create($fusionObjectTree);

return new Prototype(
PrototypeName::fromString($prototypeName),
$fusionAst,
$fusionRuntime
);
}

return null;
}
}
Loading

0 comments on commit 3612c3b

Please sign in to comment.