mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-08-20 14:43:49 +00:00
Merge remote-tracking branch 'origin/master' into issue162_ACCent_display_addresses
This commit is contained in:
@@ -504,6 +504,8 @@ class ApiController extends AbstractCRUDController
|
||||
$this->getContextForSerializationPostAlter($action, $request, $_format, $entity, [$postedData])
|
||||
);
|
||||
}
|
||||
|
||||
throw new \Exception('Unable to handle such request method.');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -10,18 +10,18 @@ use Symfony\Component\Console\Output\OutputInterface;
|
||||
/**
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop
|
||||
*
|
||||
*
|
||||
*/
|
||||
class LoadCountriesCommand extends Command
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @var EntityManager
|
||||
*/
|
||||
private $entityManager;
|
||||
|
||||
|
||||
private $availableLanguages;
|
||||
|
||||
|
||||
/**
|
||||
* LoadCountriesCommand constructor.
|
||||
*
|
||||
@@ -34,7 +34,7 @@ class LoadCountriesCommand extends Command
|
||||
$this->availableLanguages=$availableLanguages;
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-PHPdoc)
|
||||
* @see \Symfony\Component\Console\Command\Command::configure()
|
||||
@@ -45,7 +45,7 @@ class LoadCountriesCommand extends Command
|
||||
->setDescription('Load or update countries in db. This command does not delete existing countries, '.
|
||||
'but will update names according to available languages');
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-PHPdoc)
|
||||
* @see \Symfony\Component\Console\Command\Command::execute()
|
||||
@@ -54,43 +54,44 @@ class LoadCountriesCommand extends Command
|
||||
{
|
||||
$countries = static::prepareCountryList($this->availableLanguages);
|
||||
$em = $this->entityManager;
|
||||
|
||||
|
||||
foreach($countries as $country) {
|
||||
$countryStored = $em->getRepository('ChillMainBundle:Country')
|
||||
->findOneBy(array('countryCode' => $country->getCountryCode()));
|
||||
|
||||
|
||||
if (NULL === $countryStored) {
|
||||
$em->persist($country);
|
||||
} else {
|
||||
$countryStored->setName($country->getName());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$em->flush();
|
||||
}
|
||||
|
||||
public static function prepareCountryList($languages)
|
||||
{
|
||||
$regionBundle = Intl::getRegionBundle();
|
||||
|
||||
$countries = [];
|
||||
|
||||
foreach ($languages as $language) {
|
||||
$countries[$language] = $regionBundle->getCountryNames($language);
|
||||
}
|
||||
|
||||
|
||||
$countryEntities = array();
|
||||
|
||||
|
||||
foreach ($countries[$languages[0]] as $countryCode => $name) {
|
||||
$names = array();
|
||||
|
||||
|
||||
foreach ($languages as $language) {
|
||||
$names[$language] = $countries[$language][$countryCode];
|
||||
}
|
||||
|
||||
|
||||
$country = new \Chill\MainBundle\Entity\Country();
|
||||
$country->setName($names)->setCountryCode($countryCode);
|
||||
$countryEntities[] = $country;
|
||||
}
|
||||
|
||||
|
||||
return $countryEntities;
|
||||
}
|
||||
}
|
||||
|
@@ -24,26 +24,26 @@ class LoadLanguages extends AbstractFixture implements ContainerAwareInterface,
|
||||
// Array of ancien languages (to exclude)
|
||||
private $ancientToExclude = ["ang", "egy", "fro", "goh", "grc", "la", "non", "peo", "pro", "sga",
|
||||
"dum", "enm", "frm", "gmh", "mga", "akk", "phn", "zxx", "got", "und"];
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @var ContainerInterface
|
||||
*/
|
||||
private $container;
|
||||
|
||||
|
||||
public function setContainer(ContainerInterface $container = null)
|
||||
{
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
|
||||
public function getOrder() {
|
||||
return 10;
|
||||
}
|
||||
|
||||
|
||||
public function load(ObjectManager $manager) {
|
||||
|
||||
|
||||
echo "loading languages... \n";
|
||||
|
||||
|
||||
foreach (Intl::getLanguageBundle()->getLanguageNames() as $code => $language) {
|
||||
if (
|
||||
!in_array($code, $this->regionalVersionToInclude)
|
||||
@@ -58,23 +58,24 @@ class LoadLanguages extends AbstractFixture implements ContainerAwareInterface,
|
||||
$manager->persist($lang);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$manager->flush();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* prepare names for languages
|
||||
*
|
||||
* @param string $languageCode
|
||||
* Prepare names for languages.
|
||||
*
|
||||
* @return string[] languages name indexed by available language code
|
||||
*/
|
||||
private function prepareName($languageCode) {
|
||||
private function prepareName(string $languageCode): array {
|
||||
$names = [];
|
||||
|
||||
foreach ($this->container->getParameter('chill_main.available_languages') as $lang) {
|
||||
$names[$lang] = Intl::getLanguageBundle()->getLanguageName($languageCode);
|
||||
}
|
||||
|
||||
|
||||
return $names;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@@ -1,35 +1,32 @@
|
||||
<?php
|
||||
/*
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\MainBundle\DependencyInjection\CompilerPass;
|
||||
|
||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Chill\MainBundle\Form\PermissionsGroupType;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
use LogicException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Julien Fastré <julien.fastre@champs-libres.coop>
|
||||
*/
|
||||
class ACLFlagsCompilerPass implements CompilerPassInterface
|
||||
{
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
$permissionGroupType = $container->getDefinition(PermissionsGroupType::class);
|
||||
|
||||
|
||||
foreach($container->findTaggedServiceIds('chill_main.flags') as $id => $tags) {
|
||||
$reference = new Reference($id);
|
||||
|
||||
|
||||
foreach ($tags as $tag) {
|
||||
switch($tag['scope']) {
|
||||
case PermissionsGroupType::FLAG_SCOPE:
|
||||
|
||||
|
||||
$permissionGroupType->addMethodCall('addFlagProvider', [ $reference ]);
|
||||
break;
|
||||
default:
|
||||
throw new \LogicalException(sprintf(
|
||||
throw new LogicException(sprintf(
|
||||
"This tag 'scope' is not implemented: %s, on service with id %s", $tag['scope'], $id)
|
||||
);
|
||||
}
|
||||
|
@@ -19,14 +19,11 @@ class Configuration implements ConfigurationInterface
|
||||
|
||||
use AddWidgetConfigurationTrait;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var ContainerBuilder
|
||||
*/
|
||||
private $containerBuilder;
|
||||
private ContainerBuilder $containerBuilder;
|
||||
|
||||
|
||||
public function __construct(array $widgetFactories = array(),
|
||||
public function __construct(
|
||||
array $widgetFactories,
|
||||
ContainerBuilder $containerBuilder)
|
||||
{
|
||||
$this->setWidgetFactories($widgetFactories);
|
||||
|
@@ -30,27 +30,27 @@ use Chill\MainBundle\DependencyInjection\Widget\HasWidgetFactoriesExtensionInter
|
||||
|
||||
/**
|
||||
* Compile the configurations and inject required service into container.
|
||||
*
|
||||
*
|
||||
* The widgets are services tagged with :
|
||||
*
|
||||
*
|
||||
* ```
|
||||
* { name: chill_widget, alias: my_alias, place: my_place }
|
||||
* ```
|
||||
*
|
||||
* Or, if the tag does not exist or if you need to add some config to your
|
||||
*
|
||||
* Or, if the tag does not exist or if you need to add some config to your
|
||||
* service depending on the config, you should use a `WidgetFactory` (see
|
||||
* `WidgetFactoryInterface`.
|
||||
*
|
||||
* To reuse this compiler pass, simple execute the doProcess metho in your
|
||||
*
|
||||
* To reuse this compiler pass, simple execute the doProcess metho in your
|
||||
* compiler. Example :
|
||||
*
|
||||
*
|
||||
* ```
|
||||
* namespace Chill\MainBundle\DependencyInjection\CompilerPass;
|
||||
*
|
||||
*
|
||||
* use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
* use Chill\MainBundle\DependencyInjection\Widget\AbstractWidgetsCompilerPass;
|
||||
* class WidgetsCompilerPass extends AbstractWidgetsCompilerPass {
|
||||
*
|
||||
*
|
||||
* public function process(ContainerBuilder $container)
|
||||
* {
|
||||
* $this->doProcess($container, 'chill_main', 'chill_main.widgets');
|
||||
@@ -58,58 +58,58 @@ use Chill\MainBundle\DependencyInjection\Widget\HasWidgetFactoriesExtensionInter
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
abstract class AbstractWidgetsCompilerPass implements CompilerPassInterface
|
||||
{
|
||||
private $widgetServices = array();
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @var WidgetFactoryInterface[]
|
||||
*/
|
||||
private $widgetFactories;
|
||||
|
||||
|
||||
/**
|
||||
* The service which will manage the widgets
|
||||
*
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const WIDGET_MANAGER = 'chill.main.twig.widget';
|
||||
|
||||
|
||||
/**
|
||||
* the method wich register the widget into give service.
|
||||
*/
|
||||
const WIDGET_MANAGER_METHOD_REGISTER = 'addWidget';
|
||||
|
||||
|
||||
/**
|
||||
* the value of the `name` key in service definitions's tag
|
||||
*
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const WIDGET_SERVICE_TAG_NAME = 'chill_widget';
|
||||
|
||||
|
||||
/**
|
||||
* the key used to collect the alias in the service definition's tag.
|
||||
* the alias must be
|
||||
* the key used to collect the alias in the service definition's tag.
|
||||
* the alias must be
|
||||
* injected into the configuration under 'alias' key.
|
||||
*
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const WIDGET_SERVICE_TAG_ALIAS = 'alias';
|
||||
|
||||
|
||||
/**
|
||||
* the key used to collect the authorized place in the service definition's tag
|
||||
*
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const WIDGET_SERVICE_TAG_PLACES = 'place';
|
||||
|
||||
|
||||
/**
|
||||
* the key to use to order widget for a given place
|
||||
*/
|
||||
const WIDGET_CONFIG_ORDER = 'order';
|
||||
|
||||
|
||||
/**
|
||||
* the key to use to identify widget for a given place
|
||||
*/
|
||||
@@ -118,24 +118,25 @@ abstract class AbstractWidgetsCompilerPass implements CompilerPassInterface
|
||||
|
||||
/**
|
||||
* process the configuration and the container to add the widget available
|
||||
*
|
||||
*
|
||||
* @param ContainerBuilder $container
|
||||
* @param string $extension the extension of your bundle
|
||||
* @param string $containerWidgetConfigParameterName the key under which we can use the widget configuration
|
||||
* @throws \LogicException
|
||||
* @throws \UnexpectedValueException if the given extension does not implement HasWidgetExtensionInterface
|
||||
* @throws \InvalidConfigurationException if there are errors in the config
|
||||
*/
|
||||
public function doProcess(ContainerBuilder $container, $extension,
|
||||
$containerWidgetConfigParameterName)
|
||||
{
|
||||
public function doProcess(
|
||||
ContainerBuilder $container,
|
||||
$extension,
|
||||
$containerWidgetConfigParameterName
|
||||
) {
|
||||
if (!$container->hasDefinition(self::WIDGET_MANAGER)) {
|
||||
throw new \LogicException("the service ".self::WIDGET_MANAGER." should".
|
||||
" be present. It is required by ".self::class);
|
||||
}
|
||||
|
||||
|
||||
$managerDefinition = $container->getDefinition(self::WIDGET_MANAGER);
|
||||
|
||||
|
||||
// collect the widget factories
|
||||
/* @var $extensionClass HasWidgetFactoriesExtensionInterface */
|
||||
$extensionClass = $container->getExtension($extension);
|
||||
@@ -148,19 +149,19 @@ abstract class AbstractWidgetsCompilerPass implements CompilerPassInterface
|
||||
HasWidgetFactoriesExtensionInterface::class,
|
||||
get_class($extensionClass)));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
$this->widgetFactories = $extensionClass->getWidgetFactories();
|
||||
|
||||
|
||||
// collect the availabled tagged services
|
||||
$this->collectTaggedServices($container);
|
||||
|
||||
|
||||
// collect the widgets and their config :
|
||||
$widgetParameters = $container->getParameter($containerWidgetConfigParameterName);
|
||||
|
||||
|
||||
// and add them to the delegated_block
|
||||
foreach($widgetParameters as $place => $widgets) {
|
||||
|
||||
|
||||
foreach ($widgets as $param) {
|
||||
$alias = $param[self::WIDGET_CONFIG_ALIAS];
|
||||
// check that the service exists
|
||||
@@ -168,43 +169,43 @@ abstract class AbstractWidgetsCompilerPass implements CompilerPassInterface
|
||||
throw new InvalidConfigurationException(sprintf("The alias %s".
|
||||
" is not defined.", $alias));
|
||||
}
|
||||
|
||||
|
||||
// check that the widget is allowed at this place
|
||||
if (!$this->isPlaceAllowedForWidget($place, $alias, $container)) {
|
||||
throw new \InvalidConfigurationException(sprintf(
|
||||
throw new InvalidConfigurationException(sprintf(
|
||||
"The widget with alias %s is not allowed at place %s",
|
||||
$alias,
|
||||
$alias,
|
||||
$place
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
// get the order, eventually corrected
|
||||
$order = $this->cacheAndGetOrdering($place, $param[self::WIDGET_CONFIG_ORDER]);
|
||||
|
||||
$order = $this->cacheAndGetOrdering($place, $param[self::WIDGET_CONFIG_ORDER]);
|
||||
|
||||
// register the widget with config to the service, using the method
|
||||
// `addWidget`
|
||||
if ($this->widgetServices[$alias] instanceof WidgetFactoryInterface) {
|
||||
/* @var $factory WidgetFactoryInterface */
|
||||
$factory = $this->widgetServices[$alias];
|
||||
// get the config (under the key which equals to widget_alias
|
||||
$config = isset($param[$factory->getWidgetAlias()]) ?
|
||||
$config = isset($param[$factory->getWidgetAlias()]) ?
|
||||
$param[$factory->getWidgetAlias()] : array();
|
||||
// register the service into the container
|
||||
$serviceId =$this->registerServiceIntoContainer($container,
|
||||
$serviceId =$this->registerServiceIntoContainer($container,
|
||||
$factory, $place, $order, $config);
|
||||
|
||||
|
||||
$managerDefinition->addMethodCall(self::WIDGET_MANAGER_METHOD_REGISTER,
|
||||
array(
|
||||
$place,
|
||||
$order,
|
||||
new Reference($serviceId),
|
||||
$place,
|
||||
$order,
|
||||
new Reference($serviceId),
|
||||
$config
|
||||
));
|
||||
} else {
|
||||
$managerDefinition->addMethodCall(self::WIDGET_MANAGER_METHOD_REGISTER,
|
||||
array(
|
||||
$place,
|
||||
$order,
|
||||
$place,
|
||||
$order,
|
||||
new Reference($this->widgetServices[$alias]),
|
||||
array() // the config is alway an empty array
|
||||
));
|
||||
@@ -212,10 +213,10 @@ abstract class AbstractWidgetsCompilerPass implements CompilerPassInterface
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* register the service into container.
|
||||
*
|
||||
*
|
||||
* @param ContainerBuilder $container
|
||||
* @param WidgetFactoryInterface $factory
|
||||
* @param string $place
|
||||
@@ -231,28 +232,28 @@ abstract class AbstractWidgetsCompilerPass implements CompilerPassInterface
|
||||
array $config
|
||||
) {
|
||||
$serviceId = $factory->getServiceId($container, $place, $order, $config);
|
||||
$definition = $factory->createDefinition($container, $place,
|
||||
$definition = $factory->createDefinition($container, $place,
|
||||
$order, $config);
|
||||
$container->setDefinition($serviceId, $definition);
|
||||
|
||||
|
||||
return $serviceId;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* cache of ordering by place.
|
||||
*
|
||||
*
|
||||
* @internal used by function cacheAndGetOrdering
|
||||
* @var array
|
||||
*/
|
||||
private $cacheOrdering = array();
|
||||
|
||||
|
||||
/**
|
||||
* check if the ordering has already be used for the given $place and,
|
||||
* if yes, correct the ordering by incrementation of 1 until the ordering
|
||||
* has not be used.
|
||||
*
|
||||
*
|
||||
* recursive method.
|
||||
*
|
||||
*
|
||||
* @param string $place
|
||||
* @param float $ordering
|
||||
* @return float
|
||||
@@ -262,7 +263,7 @@ abstract class AbstractWidgetsCompilerPass implements CompilerPassInterface
|
||||
if (!array_key_exists($place, $this->cacheOrdering)) {
|
||||
$this->cacheOrdering[$place] = array();
|
||||
}
|
||||
|
||||
|
||||
// check if the order exists
|
||||
if (array_search($ordering, $this->cacheOrdering[$place])) {
|
||||
// if the order exists, increment of 1 and try again
|
||||
@@ -270,14 +271,14 @@ abstract class AbstractWidgetsCompilerPass implements CompilerPassInterface
|
||||
} else {
|
||||
// cache the ordering
|
||||
$this->cacheOrdering[$place][] = $ordering;
|
||||
|
||||
|
||||
return $ordering;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* get the places where the service is allowed
|
||||
*
|
||||
*
|
||||
* @param Definition $definition
|
||||
* @return unknown
|
||||
*/
|
||||
@@ -288,7 +289,7 @@ abstract class AbstractWidgetsCompilerPass implements CompilerPassInterface
|
||||
->getAllowedPlaces())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
$definition = $container->findDefinition($this->widgetServices[$widgetAlias]);
|
||||
|
||||
@@ -300,17 +301,17 @@ abstract class AbstractWidgetsCompilerPass implements CompilerPassInterface
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method collect all service tagged with `self::WIDGET_SERVICE_TAG`, and
|
||||
* add also the widget defined by factories
|
||||
*
|
||||
*
|
||||
* This method also check that the service is correctly tagged with `alias` and
|
||||
* `places`, or the factory give a correct alias and more than one place.
|
||||
*
|
||||
*
|
||||
* @param ContainerBuilder $container
|
||||
* @throws InvalidConfigurationException
|
||||
* @throws InvalidArgumentException
|
||||
@@ -320,13 +321,13 @@ abstract class AbstractWidgetsCompilerPass implements CompilerPassInterface
|
||||
// first, check the service tagged in service definition
|
||||
foreach ($container->findTaggedServiceIds(self::WIDGET_SERVICE_TAG_NAME) as $id => $attrs) {
|
||||
foreach ($attrs as $attr) {
|
||||
|
||||
|
||||
// check the alias is set
|
||||
if (!isset($attr[self::WIDGET_SERVICE_TAG_ALIAS])) {
|
||||
throw new InvalidConfigurationException("you should add an ".self::WIDGET_SERVICE_TAG_ALIAS.
|
||||
" key on the service ".$id);
|
||||
}
|
||||
|
||||
|
||||
// check the place is set
|
||||
if (!isset($attr[self::WIDGET_SERVICE_TAG_PLACES])) {
|
||||
throw new InvalidConfigurationException(sprintf(
|
||||
@@ -335,54 +336,54 @@ abstract class AbstractWidgetsCompilerPass implements CompilerPassInterface
|
||||
$id
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
// check the alias does not exists yet
|
||||
if (array_key_exists($attr[self::WIDGET_SERVICE_TAG_ALIAS], $this->widgetServices)) {
|
||||
throw new InvalidArgumentException("a service has already be defined with the ".
|
||||
self::WIDGET_SERVICE_TAG_ALIAS." ".$attr[self::WIDGET_SERVICE_TAG_ALIAS]);
|
||||
}
|
||||
|
||||
|
||||
// register the service as available
|
||||
$this->widgetServices[$attr[self::WIDGET_SERVICE_TAG_ALIAS]] = $id;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// add the services defined by factories
|
||||
foreach($this->widgetFactories as $factory) {
|
||||
/* @var $factory WidgetFactoryInterface */
|
||||
$alias = $factory->getWidgetAlias();
|
||||
|
||||
|
||||
// check the alias is not empty
|
||||
if (empty($alias)) {
|
||||
throw new \LogicException(sprintf(
|
||||
"the widget factory %s returns an empty alias",
|
||||
get_class($factory)));
|
||||
}
|
||||
|
||||
|
||||
// check the places are not empty
|
||||
if (!is_array($factory->getAllowedPlaces())) {
|
||||
throw new \UnexpectedValueException("the method 'getAllowedPlaces' "
|
||||
. "should return a non-empty array. Unexpected value on ".
|
||||
get_class($factory));
|
||||
}
|
||||
|
||||
|
||||
if (count($factory->getAllowedPlaces()) == 0) {
|
||||
throw new \LengthException("The method 'getAllowedPlaces' should "
|
||||
. "return a non-empty array, but returned 0 elements on ".
|
||||
get_class($factory).'::getAllowedPlaces()');
|
||||
}
|
||||
|
||||
|
||||
// check the alias does not exists yet
|
||||
if (array_key_exists($alias, $this->widgetServices)) {
|
||||
throw new InvalidArgumentException("a service has already be defined with the ".
|
||||
self::WIDGET_SERVICE_TAG_ALIAS." ".$alias);
|
||||
}
|
||||
|
||||
|
||||
// register the factory as available
|
||||
$this->widgetServices[$factory->getWidgetAlias()] = $factory;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@@ -4,13 +4,9 @@ namespace Chill\MainBundle\Doctrine\Model;
|
||||
|
||||
use \JsonSerializable;
|
||||
|
||||
/**
|
||||
* Description of Point
|
||||
*
|
||||
*/
|
||||
class Point implements JsonSerializable {
|
||||
private ?float $lat = null;
|
||||
private ?float $lon = null;
|
||||
private ?float $lat;
|
||||
private ?float $lon;
|
||||
public static string $SRID = '4326';
|
||||
|
||||
private function __construct(?float $lon, ?float $lat)
|
||||
@@ -22,6 +18,7 @@ class Point implements JsonSerializable {
|
||||
public function toGeoJson(): string
|
||||
{
|
||||
$array = $this->toArrayGeoJson();
|
||||
|
||||
return \json_encode($array);
|
||||
}
|
||||
|
||||
@@ -33,60 +30,53 @@ class Point implements JsonSerializable {
|
||||
public function toArrayGeoJson(): array
|
||||
{
|
||||
return [
|
||||
"type" => "Point",
|
||||
"coordinates" => [ $this->lon, $this->lat ]
|
||||
'type' => 'Point',
|
||||
'coordinates' => [$this->lon, $this->lat],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function toWKT(): string
|
||||
{
|
||||
return 'SRID='.self::$SRID.';POINT('.$this->lon.' '.$this->lat.')';
|
||||
return sprintf("SRID=%s;POINT(%s %s)", self::$SRID, $this->lon, $this->lat);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param type $geojson
|
||||
* @return Point
|
||||
*/
|
||||
public static function fromGeoJson(string $geojson): Point
|
||||
public static function fromGeoJson(string $geojson): self
|
||||
{
|
||||
$a = json_decode($geojson);
|
||||
//check if the geojson string is correct
|
||||
if (NULL === $a or !isset($a->type) or !isset($a->coordinates)){
|
||||
|
||||
if (null === $a) {
|
||||
throw PointException::badJsonString($geojson);
|
||||
}
|
||||
|
||||
if ($a->type != 'Point'){
|
||||
if (null === $a->type || null === $a->coordinates) {
|
||||
throw PointException::badJsonString($geojson);
|
||||
}
|
||||
|
||||
if ($a->type !== 'Point'){
|
||||
throw PointException::badGeoType();
|
||||
}
|
||||
|
||||
$lat = $a->coordinates[1];
|
||||
$lon = $a->coordinates[0];
|
||||
[$lon, $lat] = $a->coordinates;
|
||||
|
||||
return Point::fromLonLat($lon, $lat);
|
||||
}
|
||||
|
||||
public static function fromLonLat(float $lon, float $lat): Point
|
||||
public static function fromLonLat(float $lon, float $lat): self
|
||||
{
|
||||
if (($lon > -180 && $lon < 180) && ($lat > -90 && $lat < 90))
|
||||
{
|
||||
if (($lon > -180 && $lon < 180) && ($lat > -90 && $lat < 90)) {
|
||||
return new Point($lon, $lat);
|
||||
} else {
|
||||
throw PointException::badCoordinates($lon, $lat);
|
||||
}
|
||||
|
||||
throw PointException::badCoordinates($lon, $lat);
|
||||
}
|
||||
|
||||
public static function fromArrayGeoJson(array $array): Point
|
||||
public static function fromArrayGeoJson(array $array): self
|
||||
{
|
||||
if ($array['type'] == 'Point' &&
|
||||
isset($array['coordinates']))
|
||||
{
|
||||
if ($array['type'] === 'Point' && isset($array['coordinates'])) {
|
||||
return self::fromLonLat($array['coordinates'][0], $array['coordinates'][1]);
|
||||
}
|
||||
|
||||
throw new \Exception('Unable to build a point from input data.');
|
||||
}
|
||||
|
||||
public function getLat(): float
|
||||
|
@@ -51,8 +51,10 @@ class CenterTransformer implements DataTransformerInterface
|
||||
}
|
||||
}
|
||||
|
||||
$ids = [];
|
||||
|
||||
if ($this->multiple) {
|
||||
$ids = \explode(',', $id);
|
||||
$ids = explode(',', $id);
|
||||
} else {
|
||||
$ids[] = (int) $id;
|
||||
}
|
||||
@@ -68,9 +70,9 @@ class CenterTransformer implements DataTransformerInterface
|
||||
|
||||
if ($this->multiple) {
|
||||
return new ArrayCollection($centers);
|
||||
} else {
|
||||
return $centers[0];
|
||||
}
|
||||
|
||||
return $centers[0];
|
||||
}
|
||||
|
||||
public function transform($center)
|
||||
|
@@ -4,6 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace Chill\MainBundle\Repository;
|
||||
|
||||
use Chill\MainBundle\Entity\GroupCenter;
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
|
@@ -139,7 +139,7 @@ class SearchApi
|
||||
return $nq->getResult();
|
||||
}
|
||||
|
||||
private function prepareProviders($rawResults)
|
||||
private function prepareProviders(array $rawResults)
|
||||
{
|
||||
$metadatas = [];
|
||||
foreach ($rawResults as $r) {
|
||||
@@ -156,8 +156,10 @@ class SearchApi
|
||||
}
|
||||
}
|
||||
|
||||
private function buildResults($rawResults)
|
||||
private function buildResults(array $rawResults): array
|
||||
{
|
||||
$items = [];
|
||||
|
||||
foreach ($rawResults as $r) {
|
||||
foreach ($this->providers as $k => $p) {
|
||||
if ($p->supportsResult($r['key'], $r['metadata'])) {
|
||||
@@ -170,6 +172,6 @@ class SearchApi
|
||||
}
|
||||
}
|
||||
|
||||
return $items ?? [];
|
||||
return $items;
|
||||
}
|
||||
}
|
||||
|
@@ -98,5 +98,7 @@ class PasswordRecoverVoter extends Voter
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\MainBundle\Serializer\Normalizer;
|
||||
|
||||
use Chill\MainBundle\Entity\Address;
|
||||
@@ -12,31 +14,41 @@ class AddressNormalizer implements NormalizerAwareInterface, NormalizerInterface
|
||||
{
|
||||
use NormalizerAwareTrait;
|
||||
|
||||
/**
|
||||
* @param Address $address
|
||||
*/
|
||||
public function normalize($address, string $format = null, array $context = [])
|
||||
{
|
||||
/** @var Address $address */
|
||||
$data['address_id'] = $address->getId();
|
||||
$data['text'] = $address->isNoAddress() ? '' : $address->getStreetNumber().', '.$address->getStreet();
|
||||
$data['street'] = $address->getStreet();
|
||||
$data['streetNumber'] = $address->getStreetNumber();
|
||||
$data['postcode']['id'] = $address->getPostCode()->getId();
|
||||
$data['postcode']['name'] = $address->getPostCode()->getName();
|
||||
$data['postcode']['code'] = $address->getPostCode()->getCode();
|
||||
$data['country']['id'] = $address->getPostCode()->getCountry()->getId();
|
||||
$data['country']['name'] = $address->getPostCode()->getCountry()->getName();
|
||||
$data['country']['code'] = $address->getPostCode()->getCountry()->getCountryCode();
|
||||
$data['floor'] = $address->getFloor();
|
||||
$data['corridor'] = $address->getCorridor();
|
||||
$data['steps'] = $address->getSteps();
|
||||
$data['flat'] = $address->getFlat();
|
||||
$data['buildingName'] = $address->getBuildingName();
|
||||
$data['distribution'] = $address->getDistribution();
|
||||
$data['extra'] = $address->getExtra();
|
||||
$data['validFrom'] = $address->getValidFrom();
|
||||
$data['validTo'] = $address->getValidTo();
|
||||
$data['addressReference'] = $this->normalizer->normalize($address->getAddressReference(), $format, [
|
||||
AbstractNormalizer::GROUPS => ['read']
|
||||
]);
|
||||
$data = [
|
||||
'address_id' => $address->getId(),
|
||||
'text' => $address->isNoAddress() ? '' : $address->getStreetNumber().', '.$address->getStreet(),
|
||||
'street' => $address->getStreet(),
|
||||
'streetNumber' => $address->getStreetNumber(),
|
||||
'postcode' => [
|
||||
'id' => $address->getPostCode()->getId(),
|
||||
'name' => $address->getPostCode()->getName(),
|
||||
'code' => $address->getPostCode()->getCode(),
|
||||
],
|
||||
'country' => [
|
||||
'id' => $address->getPostCode()->getCountry()->getId(),
|
||||
'name' => $address->getPostCode()->getCountry()->getName(),
|
||||
'code' => $address->getPostCode()->getCountry()->getCountryCode(),
|
||||
],
|
||||
'floor' => $address->getFloor(),
|
||||
'corridor' => $address->getCorridor(),
|
||||
'steps' => $address->getSteps(),
|
||||
'flat' => $address->getFlat(),
|
||||
'buildingName' => $address->getBuildingName(),
|
||||
'distribution' => $address->getDistribution(),
|
||||
'extra' => $address->getExtra(),
|
||||
'validFrom' => $address->getValidFrom(),
|
||||
'validTo' => $address->getValidTo(),
|
||||
'addressReference' => $this->normalizer->normalize(
|
||||
$address->getAddressReference(),
|
||||
$format,
|
||||
[AbstractNormalizer::GROUPS => ['read']]
|
||||
),
|
||||
];
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
@@ -9,32 +9,30 @@ use Symfony\Component\Serializer\Normalizer\NormalizerAwareTrait;
|
||||
|
||||
class CollectionNormalizer implements NormalizerInterface, NormalizerAwareInterface
|
||||
{
|
||||
use NormalizerAwareTrait;
|
||||
use NormalizerAwareTrait;
|
||||
|
||||
/**
|
||||
* @param Collection $collection
|
||||
*/
|
||||
public function normalize($collection, string $format = null, array $context = [])
|
||||
{
|
||||
$paginator = $collection->getPaginator();
|
||||
|
||||
return [
|
||||
'count' => $paginator->getTotalItems(),
|
||||
'pagination' => [
|
||||
'first' => $paginator->getCurrentPageFirstItemNumber(),
|
||||
'items_per_page' => $paginator->getItemsPerPage(),
|
||||
'next' => $paginator->hasNextPage() ? $paginator->getNextPage()->generateUrl() : null,
|
||||
'previous' => $paginator->hasPreviousPage() ? $paginator->getPreviousPage()->generateUrl() : null,
|
||||
'more' => $paginator->hasNextPage(),
|
||||
],
|
||||
'results' => $this->normalizer->normalize($collection->getItems(), $format, $context),
|
||||
];
|
||||
}
|
||||
|
||||
public function supportsNormalization($data, string $format = null): bool
|
||||
{
|
||||
return $data instanceof Collection;
|
||||
}
|
||||
|
||||
public function normalize($collection, string $format = null, array $context = [])
|
||||
{
|
||||
/** @var $collection Collection */
|
||||
$paginator = $collection->getPaginator();
|
||||
|
||||
$data['count'] = $paginator->getTotalItems();
|
||||
$pagination['first'] = $paginator->getCurrentPageFirstItemNumber();
|
||||
$pagination['items_per_page'] = $paginator->getItemsPerPage();
|
||||
$pagination['next'] = $paginator->hasNextPage() ?
|
||||
$paginator->getNextPage()->generateUrl() : null;
|
||||
$pagination['previous'] = $paginator->hasPreviousPage() ?
|
||||
$paginator->getPreviousPage()->generateUrl() : null;
|
||||
$pagination['more'] = $paginator->hasNextPage();
|
||||
$data['pagination'] = $pagination;
|
||||
|
||||
// normalize results
|
||||
$data['results'] = $this->normalizer->normalize($collection->getItems(),
|
||||
$format, $context);
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
@@ -37,6 +37,18 @@ class DateRangeCoveringTest extends TestCase
|
||||
$this->assertNotContains(3, $cover->getIntersections()[0][2]);
|
||||
}
|
||||
|
||||
public function testCoveringWithMinCover1_NoCoveringWithNullDates()
|
||||
{
|
||||
$cover = new DateRangeCovering(1, new \DateTimeZone('Europe/Brussels'));
|
||||
$cover
|
||||
->add(new \DateTime('2021-10-05'), new \DateTime('2021-10-18'), 521)
|
||||
->add(new \DateTime('2021-10-26'), null, 663)
|
||||
->compute()
|
||||
;
|
||||
|
||||
$this->assertFalse($cover->hasIntersections());
|
||||
}
|
||||
|
||||
public function testCoveringWithMinCover1WithTwoIntersections()
|
||||
{
|
||||
$cover = new DateRangeCovering(1, new \DateTimeZone('Europe/Brussels'));
|
||||
|
@@ -291,11 +291,12 @@ class TimelineBuilder implements ContainerAwareInterface
|
||||
$entitiesByType[$result['type']][$result['id']], //the entity
|
||||
$context,
|
||||
$args);
|
||||
$timelineEntry['date'] = new \DateTime($result['date']);
|
||||
$timelineEntry['template'] = $data['template'];
|
||||
$timelineEntry['template_data'] = $data['template_data'];
|
||||
|
||||
$timelineEntries[] = $timelineEntry;
|
||||
$timelineEntries[] = [
|
||||
'date' => new \DateTime($result['date']),
|
||||
'template' => $data['template'],
|
||||
'template_data' => $data['template_data']
|
||||
];
|
||||
}
|
||||
|
||||
return $this->container->get('templating')
|
||||
|
@@ -5,15 +5,15 @@ namespace Chill\MainBundle\Util;
|
||||
/**
|
||||
* Utilities to compare date periods
|
||||
*
|
||||
* This class allow to compare periods when there are period covering. The
|
||||
* This class allow to compare periods when there are period covering. The
|
||||
* argument `minCovers` allow to find also when there are more than 2 period
|
||||
* which intersects.
|
||||
* which intersects.
|
||||
*
|
||||
* Example: a team may have maximum 2 leaders on a same period: you will
|
||||
* Example: a team may have maximum 2 leaders on a same period: you will
|
||||
* find here all periods where there are more than 2 leaders.
|
||||
*
|
||||
* Usage:
|
||||
*
|
||||
*
|
||||
* ```php
|
||||
* $cover = new DateRangeCovering(2); // 2 means we will have periods
|
||||
* // when there are 2+ periods intersecting
|
||||
@@ -73,7 +73,7 @@ class DateRangeCovering
|
||||
$this->addToSequence($start->getTimestamp(), $k, null);
|
||||
$this->addToSequence(
|
||||
NULL === $end ? PHP_INT_MAX : $end->getTimestamp(), null, $k
|
||||
);
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -140,72 +140,11 @@ class DateRangeCovering
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function process(array $intersections): array
|
||||
{
|
||||
$result = [];
|
||||
$starts = [];
|
||||
$ends = [];
|
||||
$metadatas = [];
|
||||
|
||||
while (null !== ($current = \array_pop($intersections))) {
|
||||
list($cStart, $cEnd, $cMetadata) = $current;
|
||||
$n = count($cMetadata);
|
||||
|
||||
foreach ($intersections as list($iStart, $iEnd, $iMetadata)) {
|
||||
$start = max($cStart, $iStart);
|
||||
$end = min($cEnd, $iEnd);
|
||||
|
||||
if ($start <= $end) {
|
||||
if (FALSE !== ($key = \array_search($start, $starts))) {
|
||||
if ($ends[$key] === $end) {
|
||||
$metadatas[$key] = \array_unique(\array_merge($metadatas[$key], $iMetadata));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$starts[] = $start;
|
||||
$ends[] = $end;
|
||||
$metadatas[] = \array_unique(\array_merge($iMetadata, $cMetadata));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// recompose results
|
||||
foreach ($starts as $k => $start) {
|
||||
$result[] = [$start, $ends[$k], \array_unique($metadatas[$k])];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function addToIntersections(array $intersections, array $intersection)
|
||||
{
|
||||
$foundExisting = false;
|
||||
list($nStart, $nEnd, $nMetadata) = $intersection;
|
||||
|
||||
\array_walk($intersections,
|
||||
function(&$i, $key) use ($nStart, $nEnd, $nMetadata, $foundExisting) {
|
||||
if ($foundExisting) {
|
||||
return;
|
||||
};
|
||||
if ($i[0] === $nStart && $i[1] === $nEnd) {
|
||||
$foundExisting = true;
|
||||
$i[2] = \array_merge($i[2], $nMetadata);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
if (!$foundExisting) {
|
||||
$intersections[] = $intersection;
|
||||
}
|
||||
|
||||
return $intersections;
|
||||
}
|
||||
|
||||
public function hasIntersections(): bool
|
||||
{
|
||||
if (!$this->computed) {
|
||||
throw new \LogicException(sprintf("You cannot call the method %s before ".
|
||||
"'process'", __METHOD));
|
||||
"'process'", __METHOD__));
|
||||
}
|
||||
|
||||
return count($this->intersections) > 0;
|
||||
@@ -215,7 +154,7 @@ class DateRangeCovering
|
||||
{
|
||||
if (!$this->computed) {
|
||||
throw new \LogicException(sprintf("You cannot call the method %s before ".
|
||||
"'process'", __METHOD));
|
||||
"'process'", __METHOD__));
|
||||
}
|
||||
|
||||
return $this->intersections;
|
||||
|
Reference in New Issue
Block a user