<?php
namespace App\Service;
use Doctrine\Common\Annotations\AnnotationReader;
use Exception;
use Symfony\Bridge\Doctrine\RegistryInterface;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\KernelInterface;
/**
* ProtoCMS Services - accessible anywhere
* USAGE in Controller : Typehint ServiceController or use Dependency Injection
* $this->serviceController->testFunction();.
*/
class ServiceController extends Controller
{
protected \Symfony\Component\HttpKernel\KernelInterface $kernel;
protected $container;
protected \Symfony\Bridge\Doctrine\RegistryInterface $doctrine;
protected $projectRoot;
public function __construct(KernelInterface $kernel, RegistryInterface $doctrine, $projectRoot)
{
$this->kernel = $kernel;
$this->container = $this->kernel->getContainer();
$this->doctrine = $doctrine;
$this->projectRoot = $projectRoot;
}
//TODO: redirect will not work in a service - needs a rethink
public function refreshPageifLocalChanged(Request $request)
{
if ($request->query->has('_locale') && $request->query->get('_locale') != $request->getLocale()) {
$request->setLocale($request->query->get('_locale'));
$request->getSession()->set('_locale', $request->query->get('_locale'));
return $this->redirect($request->getUri());
}
}
//helper function for getInheritedCMSPage() function
//get bundle namespace for current controller
public function getBundleNamespace(Request $request)
{
$controllerpath = $request->attributes->get('_controller');
if (false !== strpos($controllerpath, '::')) {
$params = explode('::', $controllerpath);
return $params[0];
// $bundleStructure = explode('\\', $params[0]);
// return $bundleStructure[0].$bundleStructure[1];
}
throw new Exception('Controller path needs accounting for');
// $bundleStructure = explode(':', $controllerpath);
// return $bundleStructure[0];
}
//finds page entity containing the inherited_bundle_name field relating to the bundle found in the request
//used to link none CMS pages to a CMS page (inherits page data i.e. content, meta, ect...)
public function getInheritedCMSPage(Request $request)
{
$bundleName = $this->getBundleNamespace($request);
return $this->doctrine->getRepository('App:Page')->getInheritedBundleName($bundleName);
}
//Fetch cms component vars for all controllers containing the @CmsComponent annotation
public function fetchCmsComponents()
{
$cmsComponentArray = [];
$annotationReader = new AnnotationReader();
$controllersDir = $this->projectRoot.'/src/Controller';
$files = scandir($controllersDir);
foreach ($files as $file) {
[$filename, $ext] = explode('.', $file);
if ('php' != $ext) {
continue;
}
$reflectedClass = new \ReflectionClass('App\\Controller\\'.$filename);
foreach ($reflectedClass->getMethods() as $reflectedMethod) {
// the annotations
$annotations = $annotationReader->getMethodAnnotations($reflectedMethod);
if (!empty($annotations)) {
foreach ($annotations as $annotation) {
$annotationName = get_class($annotation);
$pos = stripos($annotationName, strtolower('CmsComponent'));
//var_dump($annotation);
if (false !== $pos && true == $annotation->active) {
$cmsComponentArray[] = [
'name' => $annotation->propertyName,
'slug' => $annotation->slug,
'route' => $annotation->routeName,
'slugEntity' => $annotation->slugEntity,
'bundle' => 'App',
'componentType' => $annotation->componentType,
];
}
}
}
}
}
return $cmsComponentArray;
}
public function getBundleNameFromEntity($entity, $field = null)
{
//get entity properties
$reflClass = new \ReflectionClass($entity);
$refMeth = $reflClass->getMethods();
$refProp = $reflClass->getProperties();
//get namespace
$pos = strpos($refProp[0]->class, 'Bundle');
$segments = explode('\\', $refProp[0]->class);
if (false !== $pos) {
$namespace = $segments[0].$segments[1].':'.$segments[3];
$short = $segments[3];
} else {
$namespace = $segments[0].':'.$segments[2];
$short = $segments[2];
}
//get field data
$nameMetadata = null;
if (null != $field) {
$metadata = $this->doctrine->getManager()->getClassMetadata($refProp[0]->class);
$nameMetadata = $metadata->fieldMappings[$field];
}
//print_r($nameMetadata);
return ['full' => $namespace, 'short' => $short, 'fieldmeta' => $nameMetadata];
}
//Fetch cms bundles registered with the kernel
public function fetchProtoCmsBundles()
{
$bundles = [];
$controllersDir = $this->projectRoot.'/src/Controller';
$files = scandir($controllersDir);
foreach ($files as $file) {
if (false === strpos($file, 'Controller')) {
continue;
}
[$filename, $ext] = explode('.', $file);
$bundles[] = 'App\\Controller\\'.$filename;
}
return $bundles;
}
// helper function for component redirects
public function componentRedirect($url)
{
return new Response(json_encode(['componentRedirect' => $url], JSON_THROW_ON_ERROR));
}
}