Browse Source

部署到git

master
wanghongjun 2 years ago
parent
commit
f6bb6d1000
  1. 3
      addons/weliam_smartcity/vendor/symfony/event-dispatcher/.gitignore
  2. 61
      addons/weliam_smartcity/vendor/symfony/event-dispatcher/CHANGELOG.md
  3. 407
      addons/weliam_smartcity/vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php
  4. 42
      addons/weliam_smartcity/vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcherInterface.php
  5. 136
      addons/weliam_smartcity/vendor/symfony/event-dispatcher/Debug/WrappedListener.php
  6. 152
      addons/weliam_smartcity/vendor/symfony/event-dispatcher/DependencyInjection/RegisterListenersPass.php
  7. 38
      addons/weliam_smartcity/vendor/symfony/event-dispatcher/Event.php
  8. 308
      addons/weliam_smartcity/vendor/symfony/event-dispatcher/EventDispatcher.php
  9. 82
      addons/weliam_smartcity/vendor/symfony/event-dispatcher/EventDispatcherInterface.php
  10. 46
      addons/weliam_smartcity/vendor/symfony/event-dispatcher/EventSubscriberInterface.php
  11. 175
      addons/weliam_smartcity/vendor/symfony/event-dispatcher/GenericEvent.php
  12. 102
      addons/weliam_smartcity/vendor/symfony/event-dispatcher/ImmutableEventDispatcher.php
  13. 19
      addons/weliam_smartcity/vendor/symfony/event-dispatcher/LICENSE
  14. 147
      addons/weliam_smartcity/vendor/symfony/event-dispatcher/LegacyEventDispatcherProxy.php
  15. 62
      addons/weliam_smartcity/vendor/symfony/event-dispatcher/LegacyEventProxy.php
  16. 15
      addons/weliam_smartcity/vendor/symfony/event-dispatcher/README.md
  17. 26
      addons/weliam_smartcity/vendor/symfony/event-dispatcher/Tests/ChildEventDispatcherTest.php
  18. 319
      addons/weliam_smartcity/vendor/symfony/event-dispatcher/Tests/Debug/TraceableEventDispatcherTest.php
  19. 60
      addons/weliam_smartcity/vendor/symfony/event-dispatcher/Tests/Debug/WrappedListenerTest.php
  20. 199
      addons/weliam_smartcity/vendor/symfony/event-dispatcher/Tests/DependencyInjection/RegisterListenersPassTest.php
  21. 511
      addons/weliam_smartcity/vendor/symfony/event-dispatcher/Tests/EventDispatcherTest.php
  22. 55
      addons/weliam_smartcity/vendor/symfony/event-dispatcher/Tests/EventTest.php
  23. 134
      addons/weliam_smartcity/vendor/symfony/event-dispatcher/Tests/GenericEventTest.php
  24. 100
      addons/weliam_smartcity/vendor/symfony/event-dispatcher/Tests/ImmutableEventDispatcherTest.php
  25. 63
      addons/weliam_smartcity/vendor/symfony/event-dispatcher/Tests/LegacyEventDispatcherTest.php
  26. 54
      addons/weliam_smartcity/vendor/symfony/event-dispatcher/composer.json
  27. 31
      addons/weliam_smartcity/vendor/symfony/event-dispatcher/phpunit.xml.dist
  28. 3
      addons/weliam_smartcity/vendor/symfony/mime/.gitignore
  29. 98
      addons/weliam_smartcity/vendor/symfony/mime/Address.php
  30. 22
      addons/weliam_smartcity/vendor/symfony/mime/BodyRendererInterface.php
  31. 12
      addons/weliam_smartcity/vendor/symfony/mime/CHANGELOG.md
  32. 224
      addons/weliam_smartcity/vendor/symfony/mime/CharacterStream.php
  33. 48
      addons/weliam_smartcity/vendor/symfony/mime/DependencyInjection/AddMimeTypeGuesserPass.php
  34. 593
      addons/weliam_smartcity/vendor/symfony/mime/Email.php
  35. 30
      addons/weliam_smartcity/vendor/symfony/mime/Encoder/AddressEncoderInterface.php
  36. 50
      addons/weliam_smartcity/vendor/symfony/mime/Encoder/Base64ContentEncoder.php
  37. 43
      addons/weliam_smartcity/vendor/symfony/mime/Encoder/Base64Encoder.php
  38. 45
      addons/weliam_smartcity/vendor/symfony/mime/Encoder/Base64MimeHeaderEncoder.php
  39. 32
      addons/weliam_smartcity/vendor/symfony/mime/Encoder/ContentEncoderInterface.php
  40. 37
      addons/weliam_smartcity/vendor/symfony/mime/Encoder/EightBitContentEncoder.php
  41. 28
      addons/weliam_smartcity/vendor/symfony/mime/Encoder/EncoderInterface.php
  42. 56
      addons/weliam_smartcity/vendor/symfony/mime/Encoder/IdnAddressEncoder.php
  43. 25
      addons/weliam_smartcity/vendor/symfony/mime/Encoder/MimeHeaderEncoderInterface.php
  44. 66
      addons/weliam_smartcity/vendor/symfony/mime/Encoder/QpContentEncoder.php
  45. 197
      addons/weliam_smartcity/vendor/symfony/mime/Encoder/QpEncoder.php
  46. 42
      addons/weliam_smartcity/vendor/symfony/mime/Encoder/QpMimeHeaderEncoder.php
  47. 52
      addons/weliam_smartcity/vendor/symfony/mime/Encoder/Rfc2231Encoder.php
  48. 21
      addons/weliam_smartcity/vendor/symfony/mime/Exception/AddressEncoderException.php
  49. 21
      addons/weliam_smartcity/vendor/symfony/mime/Exception/ExceptionInterface.php
  50. 21
      addons/weliam_smartcity/vendor/symfony/mime/Exception/InvalidArgumentException.php
  51. 21
      addons/weliam_smartcity/vendor/symfony/mime/Exception/LogicException.php
  52. 21
      addons/weliam_smartcity/vendor/symfony/mime/Exception/RfcComplianceException.php
  53. 21
      addons/weliam_smartcity/vendor/symfony/mime/Exception/RuntimeException.php
  54. 95
      addons/weliam_smartcity/vendor/symfony/mime/FileBinaryMimeTypeGuesser.php
  55. 65
      addons/weliam_smartcity/vendor/symfony/mime/FileinfoMimeTypeGuesser.php
  56. 281
      addons/weliam_smartcity/vendor/symfony/mime/Header/AbstractHeader.php
  57. 71
      addons/weliam_smartcity/vendor/symfony/mime/Header/DateHeader.php
  58. 67
      addons/weliam_smartcity/vendor/symfony/mime/Header/HeaderInterface.php
  59. 285
      addons/weliam_smartcity/vendor/symfony/mime/Header/Headers.php
  60. 115
      addons/weliam_smartcity/vendor/symfony/mime/Header/IdentificationHeader.php
  61. 90
      addons/weliam_smartcity/vendor/symfony/mime/Header/MailboxHeader.php
  62. 139
      addons/weliam_smartcity/vendor/symfony/mime/Header/MailboxListHeader.php
  63. 176
      addons/weliam_smartcity/vendor/symfony/mime/Header/ParameterizedHeader.php
  64. 67
      addons/weliam_smartcity/vendor/symfony/mime/Header/PathHeader.php
  65. 71
      addons/weliam_smartcity/vendor/symfony/mime/Header/UnstructuredHeader.php
  66. 19
      addons/weliam_smartcity/vendor/symfony/mime/LICENSE
  67. 142
      addons/weliam_smartcity/vendor/symfony/mime/Message.php
  68. 127
      addons/weliam_smartcity/vendor/symfony/mime/MessageConverter.php
  69. 39
      addons/weliam_smartcity/vendor/symfony/mime/MimeTypeGuesserInterface.php
  70. 3154
      addons/weliam_smartcity/vendor/symfony/mime/MimeTypes.php
  71. 34
      addons/weliam_smartcity/vendor/symfony/mime/MimeTypesInterface.php
  72. 44
      addons/weliam_smartcity/vendor/symfony/mime/NamedAddress.php
  73. 87
      addons/weliam_smartcity/vendor/symfony/mime/Part/AbstractMultipartPart.php
  74. 62
      addons/weliam_smartcity/vendor/symfony/mime/Part/AbstractPart.php
  75. 150
      addons/weliam_smartcity/vendor/symfony/mime/Part/DataPart.php
  76. 64
      addons/weliam_smartcity/vendor/symfony/mime/Part/MessagePart.php
  77. 27
      addons/weliam_smartcity/vendor/symfony/mime/Part/Multipart/AlternativePart.php
  78. 33
      addons/weliam_smartcity/vendor/symfony/mime/Part/Multipart/DigestPart.php
  79. 96
      addons/weliam_smartcity/vendor/symfony/mime/Part/Multipart/FormDataPart.php
  80. 27
      addons/weliam_smartcity/vendor/symfony/mime/Part/Multipart/MixedPart.php
  81. 57
      addons/weliam_smartcity/vendor/symfony/mime/Part/Multipart/RelatedPart.php
  82. 190
      addons/weliam_smartcity/vendor/symfony/mime/Part/TextPart.php
  83. 18
      addons/weliam_smartcity/vendor/symfony/mime/README.md
  84. 81
      addons/weliam_smartcity/vendor/symfony/mime/RawMessage.php
  85. 166
      addons/weliam_smartcity/vendor/symfony/mime/Resources/bin/update_mime_types.php
  86. 102
      addons/weliam_smartcity/vendor/symfony/mime/Tests/AbstractMimeTypeGuesserTest.php
  87. 61
      addons/weliam_smartcity/vendor/symfony/mime/Tests/AddressTest.php
  88. 87
      addons/weliam_smartcity/vendor/symfony/mime/Tests/CharacterStreamTest.php
  89. 42
      addons/weliam_smartcity/vendor/symfony/mime/Tests/DependencyInjection/AddMimeTypeGuesserPassTest.php
  90. 389
      addons/weliam_smartcity/vendor/symfony/mime/Tests/EmailTest.php
  91. 158
      addons/weliam_smartcity/vendor/symfony/mime/Tests/Encoder/Base64EncoderTest.php
  92. 23
      addons/weliam_smartcity/vendor/symfony/mime/Tests/Encoder/Base64MimeHeaderEncoderTest.php
  93. 213
      addons/weliam_smartcity/vendor/symfony/mime/Tests/Encoder/QpEncoderTest.php
  94. 139
      addons/weliam_smartcity/vendor/symfony/mime/Tests/Encoder/QpMimeHeaderEncoderTest.php
  95. 129
      addons/weliam_smartcity/vendor/symfony/mime/Tests/Encoder/Rfc2231EncoderTest.php
  96. 23
      addons/weliam_smartcity/vendor/symfony/mime/Tests/FileBinaryMimeTypeGuesserTest.php
  97. 26
      addons/weliam_smartcity/vendor/symfony/mime/Tests/FileinfoMimeTypeGuesserTest.php
  98. 1
      addons/weliam_smartcity/vendor/symfony/mime/Tests/Fixtures/mimetypes/.unknownextension
  99. 0
      addons/weliam_smartcity/vendor/symfony/mime/Tests/Fixtures/mimetypes/directory/.empty
  100. 0
      addons/weliam_smartcity/vendor/symfony/mime/Tests/Fixtures/mimetypes/other-file.example

3
addons/weliam_smartcity/vendor/symfony/event-dispatcher/.gitignore

@ -0,0 +1,3 @@
vendor/
composer.lock
phpunit.xml

61
addons/weliam_smartcity/vendor/symfony/event-dispatcher/CHANGELOG.md

@ -0,0 +1,61 @@
CHANGELOG
=========
4.3.0
-----
* The signature of the `EventDispatcherInterface::dispatch()` method should be updated to `dispatch($event, string $eventName = null)`, not doing so is deprecated
* deprecated the `Event` class, use `Symfony\Contracts\EventDispatcher\Event` instead
4.1.0
-----
* added support for invokable event listeners tagged with `kernel.event_listener` by default
* The `TraceableEventDispatcher::getOrphanedEvents()` method has been added.
* The `TraceableEventDispatcherInterface` has been deprecated.
4.0.0
-----
* removed the `ContainerAwareEventDispatcher` class
* added the `reset()` method to the `TraceableEventDispatcherInterface`
3.4.0
-----
* Implementing `TraceableEventDispatcherInterface` without the `reset()` method has been deprecated.
3.3.0
-----
* The ContainerAwareEventDispatcher class has been deprecated. Use EventDispatcher with closure factories instead.
3.0.0
-----
* The method `getListenerPriority($eventName, $listener)` has been added to the
`EventDispatcherInterface`.
* The methods `Event::setDispatcher()`, `Event::getDispatcher()`, `Event::setName()`
and `Event::getName()` have been removed.
The event dispatcher and the event name are passed to the listener call.
2.5.0
-----
* added Debug\TraceableEventDispatcher (originally in HttpKernel)
* changed Debug\TraceableEventDispatcherInterface to extend EventDispatcherInterface
* added RegisterListenersPass (originally in HttpKernel)
2.1.0
-----
* added TraceableEventDispatcherInterface
* added ContainerAwareEventDispatcher
* added a reference to the EventDispatcher on the Event
* added a reference to the Event name on the event
* added fluid interface to the dispatch() method which now returns the Event
object
* added GenericEvent event class
* added the possibility for subscribers to subscribe several times for the
same event
* added ImmutableEventDispatcher

407
addons/weliam_smartcity/vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php

@ -0,0 +1,407 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\EventDispatcher\Debug;
use Psr\EventDispatcher\StoppableEventInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\EventDispatcher\LegacyEventDispatcherProxy;
use Symfony\Component\EventDispatcher\LegacyEventProxy;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Stopwatch\Stopwatch;
use Symfony\Contracts\EventDispatcher\Event as ContractsEvent;
/**
* Collects some data about event listeners.
*
* This event dispatcher delegates the dispatching to another one.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class TraceableEventDispatcher implements TraceableEventDispatcherInterface
{
protected $logger;
protected $stopwatch;
private $callStack;
private $dispatcher;
private $wrappedListeners;
private $orphanedEvents;
private $requestStack;
private $currentRequestHash = '';
public function __construct(EventDispatcherInterface $dispatcher, Stopwatch $stopwatch, LoggerInterface $logger = null, RequestStack $requestStack = null)
{
$this->dispatcher = LegacyEventDispatcherProxy::decorate($dispatcher);
$this->stopwatch = $stopwatch;
$this->logger = $logger;
$this->wrappedListeners = [];
$this->orphanedEvents = [];
$this->requestStack = $requestStack;
}
/**
* {@inheritdoc}
*/
public function addListener($eventName, $listener, $priority = 0)
{
$this->dispatcher->addListener($eventName, $listener, $priority);
}
/**
* {@inheritdoc}
*/
public function addSubscriber(EventSubscriberInterface $subscriber)
{
$this->dispatcher->addSubscriber($subscriber);
}
/**
* {@inheritdoc}
*/
public function removeListener($eventName, $listener)
{
if (isset($this->wrappedListeners[$eventName])) {
foreach ($this->wrappedListeners[$eventName] as $index => $wrappedListener) {
if ($wrappedListener->getWrappedListener() === $listener) {
$listener = $wrappedListener;
unset($this->wrappedListeners[$eventName][$index]);
break;
}
}
}
return $this->dispatcher->removeListener($eventName, $listener);
}
/**
* {@inheritdoc}
*/
public function removeSubscriber(EventSubscriberInterface $subscriber)
{
return $this->dispatcher->removeSubscriber($subscriber);
}
/**
* {@inheritdoc}
*/
public function getListeners($eventName = null)
{
return $this->dispatcher->getListeners($eventName);
}
/**
* {@inheritdoc}
*/
public function getListenerPriority($eventName, $listener)
{
// we might have wrapped listeners for the event (if called while dispatching)
// in that case get the priority by wrapper
if (isset($this->wrappedListeners[$eventName])) {
foreach ($this->wrappedListeners[$eventName] as $index => $wrappedListener) {
if ($wrappedListener->getWrappedListener() === $listener) {
return $this->dispatcher->getListenerPriority($eventName, $wrappedListener);
}
}
}
return $this->dispatcher->getListenerPriority($eventName, $listener);
}
/**
* {@inheritdoc}
*/
public function hasListeners($eventName = null)
{
return $this->dispatcher->hasListeners($eventName);
}
/**
* {@inheritdoc}
*
* @param string|null $eventName
*/
public function dispatch($event/*, string $eventName = null*/)
{
if (null === $this->callStack) {
$this->callStack = new \SplObjectStorage();
}
$currentRequestHash = $this->currentRequestHash = $this->requestStack && ($request = $this->requestStack->getCurrentRequest()) ? spl_object_hash($request) : '';
$eventName = 1 < \func_num_args() ? func_get_arg(1) : null;
if (\is_object($event)) {
$eventName = $eventName ?? \get_class($event);
} else {
@trigger_error(sprintf('Calling the "%s::dispatch()" method with the event name as first argument is deprecated since Symfony 4.3, pass it second and provide the event object first instead.', EventDispatcherInterface::class), E_USER_DEPRECATED);
$swap = $event;
$event = $eventName ?? new Event();
$eventName = $swap;
if (!$event instanceof Event) {
throw new \TypeError(sprintf('Argument 1 passed to "%s::dispatch()" must be an instance of %s, %s given.', EventDispatcherInterface::class, Event::class, \is_object($event) ? \get_class($event) : \gettype($event)));
}
}
if (null !== $this->logger && ($event instanceof Event || $event instanceof ContractsEvent || $event instanceof StoppableEventInterface) && $event->isPropagationStopped()) {
$this->logger->debug(sprintf('The "%s" event is already stopped. No listeners have been called.', $eventName));
}
$this->preProcess($eventName);
try {
$this->beforeDispatch($eventName, $event);
try {
$e = $this->stopwatch->start($eventName, 'section');
try {
$this->dispatcher->dispatch($event, $eventName);
} finally {
if ($e->isStarted()) {
$e->stop();
}
}
} finally {
$this->afterDispatch($eventName, $event);
}
} finally {
$this->currentRequestHash = $currentRequestHash;
$this->postProcess($eventName);
}
return $event;
}
/**
* {@inheritdoc}
*
* @param Request|null $request The request to get listeners for
*/
public function getCalledListeners(/* Request $request = null */)
{
if (null === $this->callStack) {
return [];
}
$hash = 1 <= \func_num_args() && null !== ($request = func_get_arg(0)) ? spl_object_hash($request) : null;
$called = [];
foreach ($this->callStack as $listener) {
list($eventName, $requestHash) = $this->callStack->getInfo();
if (null === $hash || $hash === $requestHash) {
$called[] = $listener->getInfo($eventName);
}
}
return $called;
}
/**
* {@inheritdoc}
*
* @param Request|null $request The request to get listeners for
*/
public function getNotCalledListeners(/* Request $request = null */)
{
try {
$allListeners = $this->getListeners();
} catch (\Exception $e) {
if (null !== $this->logger) {
$this->logger->info('An exception was thrown while getting the uncalled listeners.', ['exception' => $e]);
}
// unable to retrieve the uncalled listeners
return [];
}
$hash = 1 <= \func_num_args() && null !== ($request = func_get_arg(0)) ? spl_object_hash($request) : null;
$calledListeners = [];
if (null !== $this->callStack) {
foreach ($this->callStack as $calledListener) {
list(, $requestHash) = $this->callStack->getInfo();
if (null === $hash || $hash === $requestHash) {
$calledListeners[] = $calledListener->getWrappedListener();
}
}
}
$notCalled = [];
foreach ($allListeners as $eventName => $listeners) {
foreach ($listeners as $listener) {
if (!\in_array($listener, $calledListeners, true)) {
if (!$listener instanceof WrappedListener) {
$listener = new WrappedListener($listener, null, $this->stopwatch, $this);
}
$notCalled[] = $listener->getInfo($eventName);
}
}
}
uasort($notCalled, [$this, 'sortNotCalledListeners']);
return $notCalled;
}
/**
* @param Request|null $request The request to get orphaned events for
*/
public function getOrphanedEvents(/* Request $request = null */): array
{
if (1 <= \func_num_args() && null !== $request = func_get_arg(0)) {
return $this->orphanedEvents[spl_object_hash($request)] ?? [];
}
if (!$this->orphanedEvents) {
return [];
}
return array_merge(...array_values($this->orphanedEvents));
}
public function reset()
{
$this->callStack = null;
$this->orphanedEvents = [];
$this->currentRequestHash = '';
}
/**
* Proxies all method calls to the original event dispatcher.
*
* @param string $method The method name
* @param array $arguments The method arguments
*
* @return mixed
*/
public function __call($method, $arguments)
{
return $this->dispatcher->{$method}(...$arguments);
}
/**
* Called before dispatching the event.
*
* @param object $event
*/
protected function beforeDispatch(string $eventName, $event)
{
$this->preDispatch($eventName, $event instanceof Event ? $event : new LegacyEventProxy($event));
}
/**
* Called after dispatching the event.
*
* @param object $event
*/
protected function afterDispatch(string $eventName, $event)
{
$this->postDispatch($eventName, $event instanceof Event ? $event : new LegacyEventProxy($event));
}
/**
* @deprecated since Symfony 4.3, will be removed in 5.0, use beforeDispatch instead
*/
protected function preDispatch($eventName, Event $event)
{
}
/**
* @deprecated since Symfony 4.3, will be removed in 5.0, use afterDispatch instead
*/
protected function postDispatch($eventName, Event $event)
{
}
private function preProcess($eventName)
{
if (!$this->dispatcher->hasListeners($eventName)) {
$this->orphanedEvents[$this->currentRequestHash][] = $eventName;
return;
}
foreach ($this->dispatcher->getListeners($eventName) as $listener) {
$priority = $this->getListenerPriority($eventName, $listener);
$wrappedListener = new WrappedListener($listener instanceof WrappedListener ? $listener->getWrappedListener() : $listener, null, $this->stopwatch, $this);
$this->wrappedListeners[$eventName][] = $wrappedListener;
$this->dispatcher->removeListener($eventName, $listener);
$this->dispatcher->addListener($eventName, $wrappedListener, $priority);
$this->callStack->attach($wrappedListener, [$eventName, $this->currentRequestHash]);
}
}
private function postProcess($eventName)
{
unset($this->wrappedListeners[$eventName]);
$skipped = false;
foreach ($this->dispatcher->getListeners($eventName) as $listener) {
if (!$listener instanceof WrappedListener) { // #12845: a new listener was added during dispatch.
continue;
}
// Unwrap listener
$priority = $this->getListenerPriority($eventName, $listener);
$this->dispatcher->removeListener($eventName, $listener);
$this->dispatcher->addListener($eventName, $listener->getWrappedListener(), $priority);
if (null !== $this->logger) {
$context = ['event' => $eventName, 'listener' => $listener->getPretty()];
}
if ($listener->wasCalled()) {
if (null !== $this->logger) {
$this->logger->debug('Notified event "{event}" to listener "{listener}".', $context);
}
} else {
$this->callStack->detach($listener);
}
if (null !== $this->logger && $skipped) {
$this->logger->debug('Listener "{listener}" was not called for event "{event}".', $context);
}
if ($listener->stoppedPropagation()) {
if (null !== $this->logger) {
$this->logger->debug('Listener "{listener}" stopped propagation of the event "{event}".', $context);
}
$skipped = true;
}
}
}
private function sortNotCalledListeners(array $a, array $b)
{
if (0 !== $cmp = strcmp($a['event'], $b['event'])) {
return $cmp;
}
if (\is_int($a['priority']) && !\is_int($b['priority'])) {
return 1;
}
if (!\is_int($a['priority']) && \is_int($b['priority'])) {
return -1;
}
if ($a['priority'] === $b['priority']) {
return 0;
}
if ($a['priority'] > $b['priority']) {
return -1;
}
return 1;
}
}

42
addons/weliam_smartcity/vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcherInterface.php

@ -0,0 +1,42 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\EventDispatcher\Debug;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Contracts\Service\ResetInterface;
/**
* @deprecated since Symfony 4.1
*
* @author Fabien Potencier <fabien@symfony.com>
*/
interface TraceableEventDispatcherInterface extends EventDispatcherInterface, ResetInterface
{
/**
* Gets the called listeners.
*
* @param Request|null $request The request to get listeners for
*
* @return array An array of called listeners
*/
public function getCalledListeners(/* Request $request = null */);
/**
* Gets the not called listeners.
*
* @param Request|null $request The request to get listeners for
*
* @return array An array of not called listeners
*/
public function getNotCalledListeners(/* Request $request = null */);
}

136
addons/weliam_smartcity/vendor/symfony/event-dispatcher/Debug/WrappedListener.php

@ -0,0 +1,136 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\EventDispatcher\Debug;
use Psr\EventDispatcher\StoppableEventInterface;
use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\LegacyEventProxy;
use Symfony\Component\Stopwatch\Stopwatch;
use Symfony\Component\VarDumper\Caster\ClassStub;
use Symfony\Contracts\EventDispatcher\Event as ContractsEvent;
/**
* @author Fabien Potencier <fabien@symfony.com>
*
* @final since Symfony 4.3: the "Event" type-hint on __invoke() will be replaced by "object" in 5.0
*/
class WrappedListener
{
private $listener;
private $optimizedListener;
private $name;
private $called;
private $stoppedPropagation;
private $stopwatch;
private $dispatcher;
private $pretty;
private $stub;
private $priority;
private static $hasClassStub;
public function __construct($listener, ?string $name, Stopwatch $stopwatch, EventDispatcherInterface $dispatcher = null)
{
$this->listener = $listener;
$this->optimizedListener = $listener instanceof \Closure ? $listener : (\is_callable($listener) ? \Closure::fromCallable($listener) : null);
$this->stopwatch = $stopwatch;
$this->dispatcher = $dispatcher;
$this->called = false;
$this->stoppedPropagation = false;
if (\is_array($listener)) {
$this->name = \is_object($listener[0]) ? \get_class($listener[0]) : $listener[0];
$this->pretty = $this->name.'::'.$listener[1];
} elseif ($listener instanceof \Closure) {
$r = new \ReflectionFunction($listener);
if (false !== strpos($r->name, '{closure}')) {
$this->pretty = $this->name = 'closure';
} elseif ($class = $r->getClosureScopeClass()) {
$this->name = $class->name;
$this->pretty = $this->name.'::'.$r->name;
} else {
$this->pretty = $this->name = $r->name;
}
} elseif (\is_string($listener)) {
$this->pretty = $this->name = $listener;
} else {
$this->name = \get_class($listener);
$this->pretty = $this->name.'::__invoke';
}
if (null !== $name) {
$this->name = $name;
}
if (null === self::$hasClassStub) {
self::$hasClassStub = class_exists(ClassStub::class);
}
}
public function getWrappedListener()
{
return $this->listener;
}
public function wasCalled()
{
return $this->called;
}
public function stoppedPropagation()
{
return $this->stoppedPropagation;
}
public function getPretty()
{
return $this->pretty;
}
public function getInfo($eventName)
{
if (null === $this->stub) {
$this->stub = self::$hasClassStub ? new ClassStub($this->pretty.'()', $this->listener) : $this->pretty.'()';
}
return [
'event' => $eventName,
'priority' => null !== $this->priority ? $this->priority : (null !== $this->dispatcher ? $this->dispatcher->getListenerPriority($eventName, $this->listener) : null),
'pretty' => $this->pretty,
'stub' => $this->stub,
];
}
public function __invoke(Event $event, $eventName, EventDispatcherInterface $dispatcher)
{
if ($event instanceof LegacyEventProxy) {
$event = $event->getEvent();
}
$dispatcher = $this->dispatcher ?: $dispatcher;
$this->called = true;
$this->priority = $dispatcher->getListenerPriority($eventName, $this->listener);
$e = $this->stopwatch->start($this->name, 'event_listener');
($this->optimizedListener ?? $this->listener)($event, $eventName, $dispatcher);
if ($e->isStarted()) {
$e->stop();
}
if (($event instanceof Event || $event instanceof ContractsEvent || $event instanceof StoppableEventInterface) && $event->isPropagationStopped()) {
$this->stoppedPropagation = true;
}
}
}

152
addons/weliam_smartcity/vendor/symfony/event-dispatcher/DependencyInjection/RegisterListenersPass.php

@ -0,0 +1,152 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\EventDispatcher\DependencyInjection;
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* Compiler pass to register tagged services for an event dispatcher.
*/
class RegisterListenersPass implements CompilerPassInterface
{
protected $dispatcherService;
protected $listenerTag;
protected $subscriberTag;
protected $eventAliasesParameter;
private $hotPathEvents = [];
private $hotPathTagName;
public function __construct(string $dispatcherService = 'event_dispatcher', string $listenerTag = 'kernel.event_listener', string $subscriberTag = 'kernel.event_subscriber', string $eventAliasesParameter = 'event_dispatcher.event_aliases')
{
$this->dispatcherService = $dispatcherService;
$this->listenerTag = $listenerTag;
$this->subscriberTag = $subscriberTag;
$this->eventAliasesParameter = $eventAliasesParameter;
}
public function setHotPathEvents(array $hotPathEvents, $tagName = 'container.hot_path')
{
$this->hotPathEvents = array_flip($hotPathEvents);
$this->hotPathTagName = $tagName;
return $this;
}
public function process(ContainerBuilder $container)
{
if (!$container->hasDefinition($this->dispatcherService) && !$container->hasAlias($this->dispatcherService)) {
return;
}
if ($container->hasParameter($this->eventAliasesParameter)) {
$aliases = $container->getParameter($this->eventAliasesParameter);
$container->getParameterBag()->remove($this->eventAliasesParameter);
} else {
$aliases = [];
}
$definition = $container->findDefinition($this->dispatcherService);
foreach ($container->findTaggedServiceIds($this->listenerTag, true) as $id => $events) {
foreach ($events as $event) {
$priority = isset($event['priority']) ? $event['priority'] : 0;
if (!isset($event['event'])) {
throw new InvalidArgumentException(sprintf('Service "%s" must define the "event" attribute on "%s" tags.', $id, $this->listenerTag));
}
$event['event'] = $aliases[$event['event']] ?? $event['event'];
if (!isset($event['method'])) {
$event['method'] = 'on'.preg_replace_callback([
'/(?<=\b)[a-z]/i',
'/[^a-z0-9]/i',
], function ($matches) { return strtoupper($matches[0]); }, $event['event']);
$event['method'] = preg_replace('/[^a-z0-9]/i', '', $event['method']);
if (null !== ($class = $container->getDefinition($id)->getClass()) && ($r = $container->getReflectionClass($class, false)) && !$r->hasMethod($event['method']) && $r->hasMethod('__invoke')) {
$event['method'] = '__invoke';
}
}
$definition->addMethodCall('addListener', [$event['event'], [new ServiceClosureArgument(new Reference($id)), $event['method']], $priority]);
if (isset($this->hotPathEvents[$event['event']])) {
$container->getDefinition($id)->addTag($this->hotPathTagName);
}
}
}
$extractingDispatcher = new ExtractingEventDispatcher();
foreach ($container->findTaggedServiceIds($this->subscriberTag, true) as $id => $attributes) {
$def = $container->getDefinition($id);
// We must assume that the class value has been correctly filled, even if the service is created by a factory
$class = $def->getClass();
if (!$r = $container->getReflectionClass($class)) {
throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id));
}
if (!$r->isSubclassOf(EventSubscriberInterface::class)) {
throw new InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $id, EventSubscriberInterface::class));
}
$class = $r->name;
ExtractingEventDispatcher::$aliases = $aliases;
ExtractingEventDispatcher::$subscriber = $class;
$extractingDispatcher->addSubscriber($extractingDispatcher);
foreach ($extractingDispatcher->listeners as $args) {
$args[1] = [new ServiceClosureArgument(new Reference($id)), $args[1]];
$definition->addMethodCall('addListener', $args);
if (isset($this->hotPathEvents[$args[0]])) {
$container->getDefinition($id)->addTag($this->hotPathTagName);
}
}
$extractingDispatcher->listeners = [];
ExtractingEventDispatcher::$aliases = [];
}
}
}
/**
* @internal
*/
class ExtractingEventDispatcher extends EventDispatcher implements EventSubscriberInterface
{
public $listeners = [];
public static $aliases = [];
public static $subscriber;
public function addListener($eventName, $listener, $priority = 0)
{
$this->listeners[] = [$eventName, $listener[1], $priority];
}
public static function getSubscribedEvents()
{
$events = [];
foreach ([self::$subscriber, 'getSubscribedEvents']() as $eventName => $params) {
$events[self::$aliases[$eventName] ?? $eventName] = $params;
}
return $events;
}
}

38
addons/weliam_smartcity/vendor/symfony/event-dispatcher/Event.php

@ -0,0 +1,38 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\EventDispatcher;
/**
* @deprecated since Symfony 4.3, use "Symfony\Contracts\EventDispatcher\Event" instead
*/
class Event
{
private $propagationStopped = false;
/**
* @return bool Whether propagation was already stopped for this event
*
* @deprecated since Symfony 4.3, use "Symfony\Contracts\EventDispatcher\Event" instead
*/
public function isPropagationStopped()
{
return $this->propagationStopped;
}
/**
* @deprecated since Symfony 4.3, use "Symfony\Contracts\EventDispatcher\Event" instead
*/
public function stopPropagation()
{
$this->propagationStopped = true;
}
}

308
addons/weliam_smartcity/vendor/symfony/event-dispatcher/EventDispatcher.php

@ -0,0 +1,308 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\EventDispatcher;
use Psr\EventDispatcher\StoppableEventInterface;
use Symfony\Component\EventDispatcher\Debug\WrappedListener;
use Symfony\Contracts\EventDispatcher\Event as ContractsEvent;
/**
* The EventDispatcherInterface is the central point of Symfony's event listener system.
*
* Listeners are registered on the manager and events are dispatched through the
* manager.
*
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
* @author Bernhard Schussek <bschussek@gmail.com>
* @author Fabien Potencier <fabien@symfony.com>
* @author Jordi Boggiano <j.boggiano@seld.be>
* @author Jordan Alliot <jordan.alliot@gmail.com>
* @author Nicolas Grekas <p@tchwork.com>
*/
class EventDispatcher implements EventDispatcherInterface
{
private $listeners = [];
private $sorted = [];
private $optimized;
public function __construct()
{
if (__CLASS__ === \get_class($this)) {
$this->optimized = [];
}
}
/**
* {@inheritdoc}
*
* @param string|null $eventName
*/
public function dispatch($event/*, string $eventName = null*/)
{
$eventName = 1 < \func_num_args() ? func_get_arg(1) : null;
if (\is_object($event)) {
$eventName = $eventName ?? \get_class($event);
} elseif (\is_string($event) && (null === $eventName || $eventName instanceof Event)) {
@trigger_error(sprintf('Calling the "%s::dispatch()" method with the event name as the first argument is deprecated since Symfony 4.3, pass it as the second argument and provide the event object as the first argument instead.', EventDispatcherInterface::class), E_USER_DEPRECATED);
$swap = $event;
$event = $eventName ?? new Event();
$eventName = $swap;
} else {
throw new \TypeError(sprintf('Argument 1 passed to "%s::dispatch()" must be an object, %s given.', EventDispatcherInterface::class, \is_object($event) ? \get_class($event) : \gettype($event)));
}
if (null !== $this->optimized && null !== $eventName) {
$listeners = $this->optimized[$eventName] ?? (empty($this->listeners[$eventName]) ? [] : $this->optimizeListeners($eventName));
} else {
$listeners = $this->getListeners($eventName);
}
if ($listeners) {
$this->callListeners($listeners, $eventName, $event);
}
return $event;
}
/**
* {@inheritdoc}
*/
public function getListeners($eventName = null)
{
if (null !== $eventName) {
if (empty($this->listeners[$eventName])) {
return [];
}
if (!isset($this->sorted[$eventName])) {
$this->sortListeners($eventName);
}
return $this->sorted[$eventName];
}
foreach ($this->listeners as $eventName => $eventListeners) {
if (!isset($this->sorted[$eventName])) {
$this->sortListeners($eventName);
}
}
return array_filter($this->sorted);
}
/**
* {@inheritdoc}
*/
public function getListenerPriority($eventName, $listener)
{
if (empty($this->listeners[$eventName])) {
return null;
}
if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure) {
$listener[0] = $listener[0]();
}
foreach ($this->listeners[$eventName] as $priority => &$listeners) {
foreach ($listeners as &$v) {
if ($v !== $listener && \is_array($v) && isset($v[0]) && $v[0] instanceof \Closure) {
$v[0] = $v[0]();
}
if ($v === $listener) {
return $priority;
}
}
}
return null;
}
/**
* {@inheritdoc}
*/
public function hasListeners($eventName = null)
{
if (null !== $eventName) {
return !empty($this->listeners[$eventName]);
}
foreach ($this->listeners as $eventListeners) {
if ($eventListeners) {
return true;
}
}
return false;
}
/**
* {@inheritdoc}
*/
public function addListener($eventName, $listener, $priority = 0)
{
$this->listeners[$eventName][$priority][] = $listener;
unset($this->sorted[$eventName], $this->optimized[$eventName]);
}
/**
* {@inheritdoc}
*/
public function removeListener($eventName, $listener)
{
if (empty($this->listeners[$eventName])) {
return;
}
if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure) {
$listener[0] = $listener[0]();
}
foreach ($this->listeners[$eventName] as $priority => &$listeners) {
foreach ($listeners as $k => &$v) {
if ($v !== $listener && \is_array($v) && isset($v[0]) && $v[0] instanceof \Closure) {
$v[0] = $v[0]();
}
if ($v === $listener) {
unset($listeners[$k], $this->sorted[$eventName], $this->optimized[$eventName]);
}
}
if (!$listeners) {
unset($this->listeners[$eventName][$priority]);
}
}
}
/**
* {@inheritdoc}
*/
public function addSubscriber(EventSubscriberInterface $subscriber)
{
foreach ($subscriber->getSubscribedEvents() as $eventName => $params) {
if (\is_string($params)) {
$this->addListener($eventName, [$subscriber, $params]);
} elseif (\is_string($params[0])) {
$this->addListener($eventName, [$subscriber, $params[0]], isset($params[1]) ? $params[1] : 0);
} else {
foreach ($params as $listener) {
$this->addListener($eventName, [$subscriber, $listener[0]], isset($listener[1]) ? $listener[1] : 0);
}
}
}
}
/**
* {@inheritdoc}
*/
public function removeSubscriber(EventSubscriberInterface $subscriber)
{
foreach ($subscriber->getSubscribedEvents() as $eventName => $params) {
if (\is_array($params) && \is_array($params[0])) {
foreach ($params as $listener) {
$this->removeListener($eventName, [$subscriber, $listener[0]]);
}
} else {
$this->removeListener($eventName, [$subscriber, \is_string($params) ? $params : $params[0]]);
}
}
}
/**
* Triggers the listeners of an event.
*
* This method can be overridden to add functionality that is executed
* for each listener.
*
* @param callable[] $listeners The event listeners
* @param string $eventName The name of the event to dispatch
* @param object $event The event object to pass to the event handlers/listeners
*/
protected function callListeners(iterable $listeners, string $eventName, $event)
{
if ($event instanceof Event) {
$this->doDispatch($listeners, $eventName, $event);
return;
}
$stoppable = $event instanceof ContractsEvent || $event instanceof StoppableEventInterface;
foreach ($listeners as $listener) {
if ($stoppable && $event->isPropagationStopped()) {
break;
}
// @deprecated: the ternary operator is part of a BC layer and should be removed in 5.0
$listener($listener instanceof WrappedListener ? new LegacyEventProxy($event) : $event, $eventName, $this);
}
}
/**
* @deprecated since Symfony 4.3, use callListeners() instead
*/
protected function doDispatch($listeners, $eventName, Event $event)
{
foreach ($listeners as $listener) {
if ($event->isPropagationStopped()) {
break;
}
$listener($event, $eventName, $this);
}
}
/**
* Sorts the internal list of listeners for the given event by priority.
*/
private function sortListeners(string $eventName)
{
krsort($this->listeners[$eventName]);
$this->sorted[$eventName] = [];
foreach ($this->listeners[$eventName] as &$listeners) {
foreach ($listeners as $k => $listener) {
if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure) {
$listener[0] = $listener[0]();
}
$this->sorted[$eventName][] = $listener;
}
}
}
/**
* Optimizes the internal list of listeners for the given event by priority.
*/
private function optimizeListeners(string $eventName): array
{
krsort($this->listeners[$eventName]);
$this->optimized[$eventName] = [];
foreach ($this->listeners[$eventName] as &$listeners) {
foreach ($listeners as &$listener) {
$closure = &$this->optimized[$eventName][];
if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure) {
$closure = static function (...$args) use (&$listener, &$closure) {
if ($listener[0] instanceof \Closure) {
$listener[0] = $listener[0]();
}
($closure = \Closure::fromCallable($listener))(...$args);
};
} else {
$closure = $listener instanceof \Closure || $listener instanceof WrappedListener ? $listener : \Closure::fromCallable($listener);
}
}
}
return $this->optimized[$eventName];
}
}

82
addons/weliam_smartcity/vendor/symfony/event-dispatcher/EventDispatcherInterface.php

@ -0,0 +1,82 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\EventDispatcher;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface as ContractsEventDispatcherInterface;
/**
* The EventDispatcherInterface is the central point of Symfony's event listener system.
* Listeners are registered on the manager and events are dispatched through the
* manager.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*/
interface EventDispatcherInterface extends ContractsEventDispatcherInterface
{
/**
* Adds an event listener that listens on the specified events.
*
* @param string $eventName The event to listen on
* @param callable $listener The listener
* @param int $priority The higher this value, the earlier an event
* listener will be triggered in the chain (defaults to 0)
*/
public function addListener($eventName, $listener, $priority = 0);
/**
* Adds an event subscriber.
*
* The subscriber is asked for all the events it is
* interested in and added as a listener for these events.
*/
public function addSubscriber(EventSubscriberInterface $subscriber);
/**
* Removes an event listener from the specified events.
*
* @param string $eventName The event to remove a listener from
* @param callable $listener The listener to remove
*/
public function removeListener($eventName, $listener);
public function removeSubscriber(EventSubscriberInterface $subscriber);
/**
* Gets the listeners of a specific event or all listeners sorted by descending priority.
*
* @param string|null $eventName The name of the event
*
* @return array The event listeners for the specified event, or all event listeners by event name
*/
public function getListeners($eventName = null);
/**
* Gets the listener priority for a specific event.
*
* Returns null if the event or the listener does not exist.
*
* @param string $eventName The name of the event
* @param callable $listener The listener
*
* @return int|null The event listener priority
*/
public function getListenerPriority($eventName, $listener);
/**
* Checks whether an event has any registered listeners.
*
* @param string|null $eventName The name of the event
*
* @return bool true if the specified event has any listeners, false otherwise
*/
public function hasListeners($eventName = null);
}

46
addons/weliam_smartcity/vendor/symfony/event-dispatcher/EventSubscriberInterface.php

@ -0,0 +1,46 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\EventDispatcher;
/**
* An EventSubscriber knows itself what events it is interested in.
* If an EventSubscriber is added to an EventDispatcherInterface, the manager invokes
* {@link getSubscribedEvents} and registers the subscriber as a listener for all
* returned events.
*
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
* @author Bernhard Schussek <bschussek@gmail.com>
*/
interface EventSubscriberInterface
{
/**
* Returns an array of event names this subscriber wants to listen to.
*
* The array keys are event names and the value can be:
*
* * The method name to call (priority defaults to 0)
* * An array composed of the method name to call and the priority
* * An array of arrays composed of the method names to call and respective
* priorities, or 0 if unset
*
* For instance:
*
* * ['eventName' => 'methodName']
* * ['eventName' => ['methodName', $priority]]
* * ['eventName' => [['methodName1', $priority], ['methodName2']]]
*
* @return array The event names to listen to
*/
public static function getSubscribedEvents();
}

175
addons/weliam_smartcity/vendor/symfony/event-dispatcher/GenericEvent.php

@ -0,0 +1,175 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\EventDispatcher;
/**
* Event encapsulation class.
*
* Encapsulates events thus decoupling the observer from the subject they encapsulate.
*
* @author Drak <drak@zikula.org>
*/
class GenericEvent extends Event implements \ArrayAccess, \IteratorAggregate
{
protected $subject;
protected $arguments;
/**
* Encapsulate an event with $subject and $args.
*
* @param mixed $subject The subject of the event, usually an object or a callable
* @param array $arguments Arguments to store in the event
*/
public function __construct($subject = null, array $arguments = [])
{
$this->subject = $subject;
$this->arguments = $arguments;
}
/**
* Getter for subject property.
*
* @return mixed The observer subject
*/
public function getSubject()
{
return $this->subject;
}
/**
* Get argument by key.
*
* @param string $key Key
*
* @return mixed Contents of array key
*
* @throws \InvalidArgumentException if key is not found
*/
public function getArgument($key)
{
if ($this->hasArgument($key)) {
return $this->arguments[$key];
}
throw new \InvalidArgumentException(sprintf('Argument "%s" not found.', $key));
}
/**
* Add argument to event.
*
* @param string $key Argument name
* @param mixed $value Value
*
* @return $this
*/
public function setArgument($key, $value)
{
$this->arguments[$key] = $value;
return $this;
}
/**
* Getter for all arguments.
*
* @return array
*/
public function getArguments()
{
return $this->arguments;
}
/**
* Set args property.
*
* @param array $args Arguments
*
* @return $this
*/
public function setArguments(array $args = [])
{
$this->arguments = $args;
return $this;
}
/**
* Has argument.
*
* @param string $key Key of arguments array
*
* @return bool
*/
public function hasArgument($key)
{
return \array_key_exists($key, $this->arguments);
}
/**
* ArrayAccess for argument getter.
*
* @param string $key Array key
*
* @return mixed
*
* @throws \InvalidArgumentException if key does not exist in $this->args
*/
public function offsetGet($key)
{
return $this->getArgument($key);
}
/**
* ArrayAccess for argument setter.
*
* @param string $key Array key to set
* @param mixed $value Value
*/
public function offsetSet($key, $value)
{
$this->setArgument($key, $value);
}
/**
* ArrayAccess for unset argument.
*
* @param string $key Array key
*/
public function offsetUnset($key)
{
if ($this->hasArgument($key)) {
unset($this->arguments[$key]);
}
}
/**
* ArrayAccess has argument.
*
* @param string $key Array key
*
* @return bool
*/
public function offsetExists($key)
{
return $this->hasArgument($key);
}
/**
* IteratorAggregate for iterating over the object like an array.
*
* @return \ArrayIterator
*/
public function getIterator()
{
return new \ArrayIterator($this->arguments);
}
}

102
addons/weliam_smartcity/vendor/symfony/event-dispatcher/ImmutableEventDispatcher.php

@ -0,0 +1,102 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\EventDispatcher;
/**
* A read-only proxy for an event dispatcher.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class ImmutableEventDispatcher implements EventDispatcherInterface
{
private $dispatcher;
public function __construct(EventDispatcherInterface $dispatcher)
{
$this->dispatcher = LegacyEventDispatcherProxy::decorate($dispatcher);
}
/**
* {@inheritdoc}
*
* @param string|null $eventName
*/
public function dispatch($event/*, string $eventName = null*/)
{
$eventName = 1 < \func_num_args() ? func_get_arg(1) : null;
if (is_scalar($event)) {
// deprecated
$swap = $event;
$event = $eventName ?? new Event();
$eventName = $swap;
}
return $this->dispatcher->dispatch($event, $eventName);
}
/**
* {@inheritdoc}
*/
public function addListener($eventName, $listener, $priority = 0)
{
throw new \BadMethodCallException('Unmodifiable event dispatchers must not be modified.');
}
/**
* {@inheritdoc}
*/
public function addSubscriber(EventSubscriberInterface $subscriber)
{
throw new \BadMethodCallException('Unmodifiable event dispatchers must not be modified.');
}
/**
* {@inheritdoc}
*/
public function removeListener($eventName, $listener)
{
throw new \BadMethodCallException('Unmodifiable event dispatchers must not be modified.');
}
/**
* {@inheritdoc}
*/
public function removeSubscriber(EventSubscriberInterface $subscriber)
{
throw new \BadMethodCallException('Unmodifiable event dispatchers must not be modified.');
}
/**
* {@inheritdoc}
*/
public function getListeners($eventName = null)
{
return $this->dispatcher->getListeners($eventName);
}
/**
* {@inheritdoc}
*/
public function getListenerPriority($eventName, $listener)
{
return $this->dispatcher->getListenerPriority($eventName, $listener);
}
/**
* {@inheritdoc}
*/
public function hasListeners($eventName = null)
{
return $this->dispatcher->hasListeners($eventName);
}
}

19
addons/weliam_smartcity/vendor/symfony/event-dispatcher/LICENSE

@ -0,0 +1,19 @@
Copyright (c) 2004-2019 Fabien Potencier
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

147
addons/weliam_smartcity/vendor/symfony/event-dispatcher/LegacyEventDispatcherProxy.php

@ -0,0 +1,147 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\EventDispatcher;
use Psr\EventDispatcher\StoppableEventInterface;
use Symfony\Contracts\EventDispatcher\Event as ContractsEvent;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface as ContractsEventDispatcherInterface;
/**
* A helper class to provide BC/FC with the legacy signature of EventDispatcherInterface::dispatch().
*
* This class should be deprecated in Symfony 5.1
*
* @author Nicolas Grekas <p@tchwork.com>
*/
final class LegacyEventDispatcherProxy implements EventDispatcherInterface
{
private $dispatcher;
public static function decorate(?ContractsEventDispatcherInterface $dispatcher): ?ContractsEventDispatcherInterface
{
if (null === $dispatcher) {
return null;
}
$r = new \ReflectionMethod($dispatcher, 'dispatch');
$param2 = $r->getParameters()[1] ?? null;
if (!$param2 || !$param2->hasType() || $param2->getType()->isBuiltin()) {
return $dispatcher;
}
@trigger_error(sprintf('The signature of the "%s::dispatch()" method should be updated to "dispatch($event, string $eventName = null)", not doing so is deprecated since Symfony 4.3.', $r->class), E_USER_DEPRECATED);
$self = new self();
$self->dispatcher = $dispatcher;
return $self;
}
/**
* {@inheritdoc}
*
* @param string|null $eventName
*
* @return object
*/
public function dispatch($event/*, string $eventName = null*/)
{
$eventName = 1 < \func_num_args() ? func_get_arg(1) : null;
if (\is_object($event)) {
$eventName = $eventName ?? \get_class($event);
} elseif (\is_string($event) && (null === $eventName || $eventName instanceof Event)) {
@trigger_error(sprintf('Calling the "%s::dispatch()" method with the event name as the first argument is deprecated since Symfony 4.3, pass it as the second argument and provide the event object as the first argument instead.', ContractsEventDispatcherInterface::class), E_USER_DEPRECATED);
$swap = $event;
$event = $eventName ?? new Event();
$eventName = $swap;
} else {
throw new \TypeError(sprintf('Argument 1 passed to "%s::dispatch()" must be an object, %s given.', ContractsEventDispatcherInterface::class, \is_object($event) ? \get_class($event) : \gettype($event)));
}
$listeners = $this->getListeners($eventName);
$stoppable = $event instanceof Event || $event instanceof ContractsEvent || $event instanceof StoppableEventInterface;
foreach ($listeners as $listener) {
if ($stoppable && $event->isPropagationStopped()) {
break;
}
$listener($event, $eventName, $this);
}
return $event;
}
/**
* {@inheritdoc}
*/
public function addListener($eventName, $listener, $priority = 0)
{
return $this->dispatcher->addListener($eventName, $listener, $priority);
}
/**
* {@inheritdoc}
*/
public function addSubscriber(EventSubscriberInterface $subscriber)
{
return $this->dispatcher->addSubscriber($subscriber);
}
/**
* {@inheritdoc}
*/
public function removeListener($eventName, $listener)
{
return $this->dispatcher->removeListener($eventName, $listener);
}
/**
* {@inheritdoc}
*/
public function removeSubscriber(EventSubscriberInterface $subscriber)
{
return $this->dispatcher->removeSubscriber($subscriber);
}
/**
* {@inheritdoc}
*/
public function getListeners($eventName = null)
{
return $this->dispatcher->getListeners($eventName);
}
/**
* {@inheritdoc}
*/
public function getListenerPriority($eventName, $listener)
{
return $this->dispatcher->getListenerPriority($eventName, $listener);
}
/**
* {@inheritdoc}
*/
public function hasListeners($eventName = null)
{
return $this->dispatcher->hasListeners($eventName);
}
/**
* Proxies all method calls to the original event dispatcher.
*/
public function __call($method, $arguments)
{
return $this->dispatcher->{$method}(...$arguments);
}
}

62
addons/weliam_smartcity/vendor/symfony/event-dispatcher/LegacyEventProxy.php

@ -0,0 +1,62 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\EventDispatcher;
use Psr\EventDispatcher\StoppableEventInterface;
use Symfony\Contracts\EventDispatcher\Event as ContractsEvent;
/**
* @internal to be removed in 5.0.
*/
final class LegacyEventProxy extends Event
{
private $event;
/**
* @param object $event
*/
public function __construct($event)
{
$this->event = $event;
}
/**
* @return object $event
*/
public function getEvent()
{
return $this->event;
}
public function isPropagationStopped()
{
if (!$this->event instanceof ContractsEvent && !$this->event instanceof StoppableEventInterface) {
return false;
}
return $this->event->isPropagationStopped();
}
public function stopPropagation()
{
if (!$this->event instanceof ContractsEvent) {
return;
}
$this->event->stopPropagation();
}
public function __call($name, $args)
{
return $this->event->{$name}(...$args);
}
}

15
addons/weliam_smartcity/vendor/symfony/event-dispatcher/README.md

@ -0,0 +1,15 @@
EventDispatcher Component
=========================
The EventDispatcher component provides tools that allow your application
components to communicate with each other by dispatching events and listening to
them.
Resources
---------
* [Documentation](https://symfony.com/doc/current/components/event_dispatcher/index.html)
* [Contributing](https://symfony.com/doc/current/contributing/index.html)
* [Report issues](https://github.com/symfony/symfony/issues) and
[send Pull Requests](https://github.com/symfony/symfony/pulls)
in the [main Symfony repository](https://github.com/symfony/symfony)

26
addons/weliam_smartcity/vendor/symfony/event-dispatcher/Tests/ChildEventDispatcherTest.php

@ -0,0 +1,26 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\EventDispatcher\Tests;
use Symfony\Component\EventDispatcher\EventDispatcher;
class ChildEventDispatcherTest extends EventDispatcherTest
{
protected function createEventDispatcher()
{
return new ChildEventDispatcher();
}
}
class ChildEventDispatcher extends EventDispatcher
{
}

319
addons/weliam_smartcity/vendor/symfony/event-dispatcher/Tests/Debug/TraceableEventDispatcherTest.php

@ -0,0 +1,319 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\EventDispatcher\Tests\Debug;
use PHPUnit\Framework\TestCase;
use Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcher;
use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Stopwatch\Stopwatch;
use Symfony\Contracts\EventDispatcher\Event as ContractsEvent;
class TraceableEventDispatcherTest extends TestCase
{
public function testAddRemoveListener()
{
$dispatcher = new EventDispatcher();
$tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch());
$tdispatcher->addListener('foo', $listener = function () {});
$listeners = $dispatcher->getListeners('foo');
$this->assertCount(1, $listeners);
$this->assertSame($listener, $listeners[0]);
$tdispatcher->removeListener('foo', $listener);
$this->assertCount(0, $dispatcher->getListeners('foo'));
}
public function testGetListeners()
{
$dispatcher = new EventDispatcher();
$tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch());
$tdispatcher->addListener('foo', $listener = function () {});
$this->assertSame($dispatcher->getListeners('foo'), $tdispatcher->getListeners('foo'));
}
public function testHasListeners()
{
$dispatcher = new EventDispatcher();
$tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch());
$this->assertFalse($dispatcher->hasListeners('foo'));
$this->assertFalse($tdispatcher->hasListeners('foo'));
$tdispatcher->addListener('foo', $listener = function () {});
$this->assertTrue($dispatcher->hasListeners('foo'));
$this->assertTrue($tdispatcher->hasListeners('foo'));
}
public function testGetListenerPriority()
{
$dispatcher = new EventDispatcher();
$tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch());
$tdispatcher->addListener('foo', function () {}, 123);
$listeners = $dispatcher->getListeners('foo');
$this->assertSame(123, $tdispatcher->getListenerPriority('foo', $listeners[0]));
// Verify that priority is preserved when listener is removed and re-added
// in preProcess() and postProcess().
$tdispatcher->dispatch(new Event(), 'foo');
$listeners = $dispatcher->getListeners('foo');
$this->assertSame(123, $tdispatcher->getListenerPriority('foo', $listeners[0]));
}
public function testGetListenerPriorityWhileDispatching()
{
$tdispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch());
$priorityWhileDispatching = null;
$listener = function () use ($tdispatcher, &$priorityWhileDispatching, &$listener) {
$priorityWhileDispatching = $tdispatcher->getListenerPriority('bar', $listener);
};
$tdispatcher->addListener('bar', $listener, 5);
$tdispatcher->dispatch(new Event(), 'bar');
$this->assertSame(5, $priorityWhileDispatching);
}
public function testAddRemoveSubscriber()
{
$dispatcher = new EventDispatcher();
$tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch());
$subscriber = new EventSubscriber();
$tdispatcher->addSubscriber($subscriber);
$listeners = $dispatcher->getListeners('foo');
$this->assertCount(1, $listeners);
$this->assertSame([$subscriber, 'call'], $listeners[0]);
$tdispatcher->removeSubscriber($subscriber);
$this->assertCount(0, $dispatcher->getListeners('foo'));
}
public function testGetCalledListeners()
{
$tdispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch());
$tdispatcher->addListener('foo', function () {}, 5);
$listeners = $tdispatcher->getNotCalledListeners();
$this->assertArrayHasKey('stub', $listeners[0]);
unset($listeners[0]['stub']);
$this->assertEquals([], $tdispatcher->getCalledListeners());
$this->assertEquals([['event' => 'foo', 'pretty' => 'closure', 'priority' => 5]], $listeners);
$tdispatcher->dispatch(new Event(), 'foo');
$listeners = $tdispatcher->getCalledListeners();
$this->assertArrayHasKey('stub', $listeners[0]);
unset($listeners[0]['stub']);
$this->assertEquals([['event' => 'foo', 'pretty' => 'closure', 'priority' => 5]], $listeners);
$this->assertEquals([], $tdispatcher->getNotCalledListeners());
}
public function testClearCalledListeners()
{
$tdispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch());
$tdispatcher->addListener('foo', function () {}, 5);
$tdispatcher->dispatch(new Event(), 'foo');
$tdispatcher->reset();
$listeners = $tdispatcher->getNotCalledListeners();
$this->assertArrayHasKey('stub', $listeners[0]);
unset($listeners[0]['stub']);
$this->assertEquals([], $tdispatcher->getCalledListeners());
$this->assertEquals([['event' => 'foo', 'pretty' => 'closure', 'priority' => 5]], $listeners);
}
public function testDispatchContractsEvent()
{
$expectedEvent = new ContractsEvent();
$tdispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch());
$tdispatcher->addListener('foo', function ($event) use ($expectedEvent) {
$this->assertSame($event, $expectedEvent);
}, 5);
$tdispatcher->dispatch($expectedEvent, 'foo');
$listeners = $tdispatcher->getCalledListeners();
$this->assertArrayHasKey('stub', $listeners[0]);
}
public function testDispatchAfterReset()
{
$tdispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch());
$tdispatcher->addListener('foo', function () {}, 5);
$tdispatcher->reset();
$tdispatcher->dispatch(new Event(), 'foo');
$listeners = $tdispatcher->getCalledListeners();
$this->assertArrayHasKey('stub', $listeners[0]);
}
public function testGetCalledListenersNested()
{
$tdispatcher = null;
$dispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch());
$dispatcher->addListener('foo', function (Event $event, $eventName, $dispatcher) use (&$tdispatcher) {
$tdispatcher = $dispatcher;
$dispatcher->dispatch(new Event(), 'bar');
});
$dispatcher->addListener('bar', function (Event $event) {});
$dispatcher->dispatch(new Event(), 'foo');
$this->assertSame($dispatcher, $tdispatcher);
$this->assertCount(2, $dispatcher->getCalledListeners());
}
public function testItReturnsNoOrphanedEventsWhenCreated()
{
$tdispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch());
$events = $tdispatcher->getOrphanedEvents();
$this->assertEmpty($events);
}
public function testItReturnsOrphanedEventsAfterDispatch()
{
$tdispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch());
$tdispatcher->dispatch(new Event(), 'foo');
$events = $tdispatcher->getOrphanedEvents();
$this->assertCount(1, $events);
$this->assertEquals(['foo'], $events);
}
public function testItDoesNotReturnHandledEvents()
{
$tdispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch());
$tdispatcher->addListener('foo', function () {});
$tdispatcher->dispatch(new Event(), 'foo');
$events = $tdispatcher->getOrphanedEvents();
$this->assertEmpty($events);
}
public function testLogger()
{
$logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
$dispatcher = new EventDispatcher();
$tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch(), $logger);
$tdispatcher->addListener('foo', $listener1 = function () {});
$tdispatcher->addListener('foo', $listener2 = function () {});
$logger->expects($this->at(0))->method('debug')->with('Notified event "{event}" to listener "{listener}".', ['event' => 'foo', 'listener' => 'closure']);
$logger->expects($this->at(1))->method('debug')->with('Notified event "{event}" to listener "{listener}".', ['event' => 'foo', 'listener' => 'closure']);
$tdispatcher->dispatch(new Event(), 'foo');
}
public function testLoggerWithStoppedEvent()
{
$logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
$dispatcher = new EventDispatcher();
$tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch(), $logger);
$tdispatcher->addListener('foo', $listener1 = function (Event $event) { $event->stopPropagation(); });
$tdispatcher->addListener('foo', $listener2 = function () {});
$logger->expects($this->at(0))->method('debug')->with('Notified event "{event}" to listener "{listener}".', ['event' => 'foo', 'listener' => 'closure']);
$logger->expects($this->at(1))->method('debug')->with('Listener "{listener}" stopped propagation of the event "{event}".', ['event' => 'foo', 'listener' => 'closure']);
$logger->expects($this->at(2))->method('debug')->with('Listener "{listener}" was not called for event "{event}".', ['event' => 'foo', 'listener' => 'closure']);
$tdispatcher->dispatch(new Event(), 'foo');
}
public function testDispatchCallListeners()
{
$called = [];
$dispatcher = new EventDispatcher();
$tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch());
$tdispatcher->addListener('foo', function () use (&$called) { $called[] = 'foo1'; }, 10);
$tdispatcher->addListener('foo', function () use (&$called) { $called[] = 'foo2'; }, 20);
$tdispatcher->dispatch(new Event(), 'foo');
$this->assertSame(['foo2', 'foo1'], $called);
}
public function testDispatchNested()
{
$dispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch());
$loop = 1;
$dispatchedEvents = 0;
$dispatcher->addListener('foo', $listener1 = function () use ($dispatcher, &$loop) {
++$loop;
if (2 == $loop) {
$dispatcher->dispatch(new Event(), 'foo');
}
});
$dispatcher->addListener('foo', function () use (&$dispatchedEvents) {
++$dispatchedEvents;
});
$dispatcher->dispatch(new Event(), 'foo');
$this->assertSame(2, $dispatchedEvents);
}
public function testDispatchReusedEventNested()
{
$nestedCall = false;
$dispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch());
$dispatcher->addListener('foo', function (Event $e) use ($dispatcher) {
$dispatcher->dispatch(new Event(), 'bar', $e);
});
$dispatcher->addListener('bar', function (Event $e) use (&$nestedCall) {
$nestedCall = true;
});
$this->assertFalse($nestedCall);
$dispatcher->dispatch(new Event(), 'foo');
$this->assertTrue($nestedCall);
}
public function testListenerCanRemoveItselfWhenExecuted()
{
$eventDispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch());
$listener1 = function ($event, $eventName, EventDispatcherInterface $dispatcher) use (&$listener1) {
$dispatcher->removeListener('foo', $listener1);
};
$eventDispatcher->addListener('foo', $listener1);
$eventDispatcher->addListener('foo', function () {});
$eventDispatcher->dispatch(new Event(), 'foo');
$this->assertCount(1, $eventDispatcher->getListeners('foo'), 'expected listener1 to be removed');
}
public function testClearOrphanedEvents()
{
$tdispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch());
$tdispatcher->dispatch(new Event(), 'foo');
$events = $tdispatcher->getOrphanedEvents();
$this->assertCount(1, $events);
$tdispatcher->reset();
$events = $tdispatcher->getOrphanedEvents();
$this->assertCount(0, $events);
}
}
class EventSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return ['foo' => 'call'];
}
}

60
addons/weliam_smartcity/vendor/symfony/event-dispatcher/Tests/Debug/WrappedListenerTest.php

@ -0,0 +1,60 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\EventDispatcher\Tests\Debug;
use PHPUnit\Framework\TestCase;
use Symfony\Component\EventDispatcher\Debug\WrappedListener;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Stopwatch\Stopwatch;
class WrappedListenerTest extends TestCase
{
/**
* @dataProvider provideListenersToDescribe
*/
public function testListenerDescription($listener, $expected)
{
$wrappedListener = new WrappedListener($listener, null, $this->getMockBuilder(Stopwatch::class)->getMock(), $this->getMockBuilder(EventDispatcherInterface::class)->getMock());
$this->assertStringMatchesFormat($expected, $wrappedListener->getPretty());
}
public function provideListenersToDescribe()
{
return [
[new FooListener(), 'Symfony\Component\EventDispatcher\Tests\Debug\FooListener::__invoke'],
[[new FooListener(), 'listen'], 'Symfony\Component\EventDispatcher\Tests\Debug\FooListener::listen'],
[['Symfony\Component\EventDispatcher\Tests\Debug\FooListener', 'listenStatic'], 'Symfony\Component\EventDispatcher\Tests\Debug\FooListener::listenStatic'],
[['Symfony\Component\EventDispatcher\Tests\Debug\FooListener', 'invalidMethod'], 'Symfony\Component\EventDispatcher\Tests\Debug\FooListener::invalidMethod'],
['var_dump', 'var_dump'],
[function () {}, 'closure'],
[\Closure::fromCallable([new FooListener(), 'listen']), 'Symfony\Component\EventDispatcher\Tests\Debug\FooListener::listen'],
[\Closure::fromCallable(['Symfony\Component\EventDispatcher\Tests\Debug\FooListener', 'listenStatic']), 'Symfony\Component\EventDispatcher\Tests\Debug\FooListener::listenStatic'],
[\Closure::fromCallable(function () {}), 'closure'],
];
}
}
class FooListener
{
public function listen()
{
}
public function __invoke()
{
}
public static function listenStatic()
{
}
}

199
addons/weliam_smartcity/vendor/symfony/event-dispatcher/Tests/DependencyInjection/RegisterListenersPassTest.php

@ -0,0 +1,199 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\EventDispatcher\Tests\DependencyInjection;
use PHPUnit\Framework\TestCase;
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\EventDispatcher\DependencyInjection\RegisterListenersPass;
class RegisterListenersPassTest extends TestCase
{
/**
* Tests that event subscribers not implementing EventSubscriberInterface
* trigger an exception.
*/
public function testEventSubscriberWithoutInterface()
{
$this->expectException('InvalidArgumentException');
$builder = new ContainerBuilder();
$builder->register('event_dispatcher');
$builder->register('my_event_subscriber', 'stdClass')
->addTag('kernel.event_subscriber');
$registerListenersPass = new RegisterListenersPass();
$registerListenersPass->process($builder);
}
public function testValidEventSubscriber()
{
$services = [
'my_event_subscriber' => [0 => []],
];
$builder = new ContainerBuilder();
$eventDispatcherDefinition = $builder->register('event_dispatcher');
$builder->register('my_event_subscriber', 'Symfony\Component\EventDispatcher\Tests\DependencyInjection\SubscriberService')
->addTag('kernel.event_subscriber');
$registerListenersPass = new RegisterListenersPass();
$registerListenersPass->process($builder);
$expectedCalls = [
[
'addListener',
[
'event',
[new ServiceClosureArgument(new Reference('my_event_subscriber')), 'onEvent'],
0,
],
],
];
$this->assertEquals($expectedCalls, $eventDispatcherDefinition->getMethodCalls());
}
public function testAbstractEventListener()
{
$this->expectException('InvalidArgumentException');
$this->expectExceptionMessage('The service "foo" tagged "kernel.event_listener" must not be abstract.');
$container = new ContainerBuilder();
$container->register('foo', 'stdClass')->setAbstract(true)->addTag('kernel.event_listener', []);
$container->register('event_dispatcher', 'stdClass');
$registerListenersPass = new RegisterListenersPass();
$registerListenersPass->process($container);
}
public function testAbstractEventSubscriber()
{
$this->expectException('InvalidArgumentException');
$this->expectExceptionMessage('The service "foo" tagged "kernel.event_subscriber" must not be abstract.');
$container = new ContainerBuilder();
$container->register('foo', 'stdClass')->setAbstract(true)->addTag('kernel.event_subscriber', []);
$container->register('event_dispatcher', 'stdClass');
$registerListenersPass = new RegisterListenersPass();
$registerListenersPass->process($container);
}
public function testEventSubscriberResolvableClassName()
{
$container = new ContainerBuilder();
$container->setParameter('subscriber.class', 'Symfony\Component\EventDispatcher\Tests\DependencyInjection\SubscriberService');
$container->register('foo', '%subscriber.class%')->addTag('kernel.event_subscriber', []);
$container->register('event_dispatcher', 'stdClass');
$registerListenersPass = new RegisterListenersPass();
$registerListenersPass->process($container);
$definition = $container->getDefinition('event_dispatcher');
$expectedCalls = [
[
'addListener',
[
'event',
[new ServiceClosureArgument(new Reference('foo')), 'onEvent'],
0,
],
],
];
$this->assertEquals($expectedCalls, $definition->getMethodCalls());
}
public function testHotPathEvents()
{
$container = new ContainerBuilder();
$container->register('foo', SubscriberService::class)->addTag('kernel.event_subscriber', []);
$container->register('event_dispatcher', 'stdClass');
(new RegisterListenersPass())->setHotPathEvents(['event'])->process($container);
$this->assertTrue($container->getDefinition('foo')->hasTag('container.hot_path'));
}
public function testEventSubscriberUnresolvableClassName()
{
$this->expectException('InvalidArgumentException');
$this->expectExceptionMessage('You have requested a non-existent parameter "subscriber.class"');
$container = new ContainerBuilder();
$container->register('foo', '%subscriber.class%')->addTag('kernel.event_subscriber', []);
$container->register('event_dispatcher', 'stdClass');
$registerListenersPass = new RegisterListenersPass();
$registerListenersPass->process($container);
}
public function testInvokableEventListener()
{
$container = new ContainerBuilder();
$container->register('foo', \stdClass::class)->addTag('kernel.event_listener', ['event' => 'foo.bar']);
$container->register('bar', InvokableListenerService::class)->addTag('kernel.event_listener', ['event' => 'foo.bar']);
$container->register('baz', InvokableListenerService::class)->addTag('kernel.event_listener', ['event' => 'event']);
$container->register('event_dispatcher', \stdClass::class);
$registerListenersPass = new RegisterListenersPass();
$registerListenersPass->process($container);
$definition = $container->getDefinition('event_dispatcher');
$expectedCalls = [
[
'addListener',
[
'foo.bar',
[new ServiceClosureArgument(new Reference('foo')), 'onFooBar'],
0,
],
],
[
'addListener',
[
'foo.bar',
[new ServiceClosureArgument(new Reference('bar')), '__invoke'],
0,
],
],
[
'addListener',
[
'event',
[new ServiceClosureArgument(new Reference('baz')), 'onEvent'],
0,
],
],
];
$this->assertEquals($expectedCalls, $definition->getMethodCalls());
}
}
class SubscriberService implements \Symfony\Component\EventDispatcher\EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return [
'event' => 'onEvent',
];
}
}
class InvokableListenerService
{
public function __invoke()
{
}
public function onEvent()
{
}
}

511
addons/weliam_smartcity/vendor/symfony/event-dispatcher/Tests/EventDispatcherTest.php

@ -0,0 +1,511 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\EventDispatcher\Tests;
use PHPUnit\Framework\TestCase;
use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Contracts\EventDispatcher\Event as ContractsEvent;
class EventDispatcherTest extends TestCase
{
/* Some pseudo events */
const preFoo = 'pre.foo';
const postFoo = 'post.foo';
const preBar = 'pre.bar';
const postBar = 'post.bar';
/**
* @var EventDispatcher
*/
private $dispatcher;
private $listener;
protected function setUp(): void
{
$this->dispatcher = $this->createEventDispatcher();
$this->listener = new TestEventListener();
}
protected function tearDown(): void
{
$this->dispatcher = null;
$this->listener = null;
}
protected function createEventDispatcher()
{
return new EventDispatcher();
}
public function testInitialState()
{
$this->assertEquals([], $this->dispatcher->getListeners());
$this->assertFalse($this->dispatcher->hasListeners(self::preFoo));
$this->assertFalse($this->dispatcher->hasListeners(self::postFoo));
}
public function testAddListener()
{
$this->dispatcher->addListener('pre.foo', [$this->listener, 'preFoo']);
$this->dispatcher->addListener('post.foo', [$this->listener, 'postFoo']);
$this->assertTrue($this->dispatcher->hasListeners());
$this->assertTrue($this->dispatcher->hasListeners(self::preFoo));
$this->assertTrue($this->dispatcher->hasListeners(self::postFoo));
$this->assertCount(1, $this->dispatcher->getListeners(self::preFoo));
$this->assertCount(1, $this->dispatcher->getListeners(self::postFoo));
$this->assertCount(2, $this->dispatcher->getListeners());
}
public function testGetListenersSortsByPriority()
{
$listener1 = new TestEventListener();
$listener2 = new TestEventListener();
$listener3 = new TestEventListener();
$listener1->name = '1';
$listener2->name = '2';
$listener3->name = '3';
$this->dispatcher->addListener('pre.foo', [$listener1, 'preFoo'], -10);
$this->dispatcher->addListener('pre.foo', [$listener2, 'preFoo'], 10);
$this->dispatcher->addListener('pre.foo', [$listener3, 'preFoo']);
$expected = [
[$listener2, 'preFoo'],
[$listener3, 'preFoo'],
[$listener1, 'preFoo'],
];
$this->assertSame($expected, $this->dispatcher->getListeners('pre.foo'));
}
public function testGetAllListenersSortsByPriority()
{
$listener1 = new TestEventListener();
$listener2 = new TestEventListener();
$listener3 = new TestEventListener();
$listener4 = new TestEventListener();
$listener5 = new TestEventListener();
$listener6 = new TestEventListener();
$this->dispatcher->addListener('pre.foo', $listener1, -10);
$this->dispatcher->addListener('pre.foo', $listener2);
$this->dispatcher->addListener('pre.foo', $listener3, 10);
$this->dispatcher->addListener('post.foo', $listener4, -10);
$this->dispatcher->addListener('post.foo', $listener5);
$this->dispatcher->addListener('post.foo', $listener6, 10);
$expected = [
'pre.foo' => [$listener3, $listener2, $listener1],
'post.foo' => [$listener6, $listener5, $listener4],
];
$this->assertSame($expected, $this->dispatcher->getListeners());
}
public function testGetListenerPriority()
{
$listener1 = new TestEventListener();
$listener2 = new TestEventListener();
$this->dispatcher->addListener('pre.foo', $listener1, -10);
$this->dispatcher->addListener('pre.foo', $listener2);
$this->assertSame(-10, $this->dispatcher->getListenerPriority('pre.foo', $listener1));
$this->assertSame(0, $this->dispatcher->getListenerPriority('pre.foo', $listener2));
$this->assertNull($this->dispatcher->getListenerPriority('pre.bar', $listener2));
$this->assertNull($this->dispatcher->getListenerPriority('pre.foo', function () {}));
}
public function testDispatch()
{
$this->dispatcher->addListener('pre.foo', [$this->listener, 'preFoo']);
$this->dispatcher->addListener('post.foo', [$this->listener, 'postFoo']);
$this->dispatcher->dispatch(new Event(), self::preFoo);
$this->assertTrue($this->listener->preFooInvoked);
$this->assertFalse($this->listener->postFooInvoked);
$this->assertInstanceOf('Symfony\Component\EventDispatcher\Event', $this->dispatcher->dispatch(new Event(), 'noevent'));
$this->assertInstanceOf('Symfony\Component\EventDispatcher\Event', $this->dispatcher->dispatch(new Event(), self::preFoo));
$event = new Event();
$return = $this->dispatcher->dispatch($event, self::preFoo);
$this->assertSame($event, $return);
}
public function testDispatchContractsEvent()
{
$this->dispatcher->addListener('pre.foo', [$this->listener, 'preFoo']);
$this->dispatcher->addListener('post.foo', [$this->listener, 'postFoo']);
$this->dispatcher->dispatch(new ContractsEvent(), self::preFoo);
$this->assertTrue($this->listener->preFooInvoked);
$this->assertFalse($this->listener->postFooInvoked);
$this->assertInstanceOf('Symfony\Component\EventDispatcher\Event', $this->dispatcher->dispatch(new Event(), 'noevent'));
$this->assertInstanceOf('Symfony\Component\EventDispatcher\Event', $this->dispatcher->dispatch(new Event(), self::preFoo));
$event = new Event();
$return = $this->dispatcher->dispatch($event, self::preFoo);
$this->assertSame($event, $return);
}
public function testDispatchForClosure()
{
$invoked = 0;
$listener = function () use (&$invoked) {
++$invoked;
};
$this->dispatcher->addListener('pre.foo', $listener);
$this->dispatcher->addListener('post.foo', $listener);
$this->dispatcher->dispatch(new Event(), self::preFoo);
$this->assertEquals(1, $invoked);
}
public function testStopEventPropagation()
{
$otherListener = new TestEventListener();
// postFoo() stops the propagation, so only one listener should
// be executed
// Manually set priority to enforce $this->listener to be called first
$this->dispatcher->addListener('post.foo', [$this->listener, 'postFoo'], 10);
$this->dispatcher->addListener('post.foo', [$otherListener, 'postFoo']);
$this->dispatcher->dispatch(new Event(), self::postFoo);
$this->assertTrue($this->listener->postFooInvoked);
$this->assertFalse($otherListener->postFooInvoked);
}
public function testDispatchByPriority()
{
$invoked = [];
$listener1 = function () use (&$invoked) {
$invoked[] = '1';
};
$listener2 = function () use (&$invoked) {
$invoked[] = '2';
};
$listener3 = function () use (&$invoked) {
$invoked[] = '3';
};
$this->dispatcher->addListener('pre.foo', $listener1, -10);
$this->dispatcher->addListener('pre.foo', $listener2);
$this->dispatcher->addListener('pre.foo', $listener3, 10);
$this->dispatcher->dispatch(new Event(), self::preFoo);
$this->assertEquals(['3', '2', '1'], $invoked);
}
public function testRemoveListener()
{
$this->dispatcher->addListener('pre.bar', $this->listener);
$this->assertTrue($this->dispatcher->hasListeners(self::preBar));
$this->dispatcher->removeListener('pre.bar', $this->listener);
$this->assertFalse($this->dispatcher->hasListeners(self::preBar));
$this->dispatcher->removeListener('notExists', $this->listener);
}
public function testAddSubscriber()
{
$eventSubscriber = new TestEventSubscriber();
$this->dispatcher->addSubscriber($eventSubscriber);
$this->assertTrue($this->dispatcher->hasListeners(self::preFoo));
$this->assertTrue($this->dispatcher->hasListeners(self::postFoo));
}
public function testAddSubscriberWithPriorities()
{
$eventSubscriber = new TestEventSubscriber();
$this->dispatcher->addSubscriber($eventSubscriber);
$eventSubscriber = new TestEventSubscriberWithPriorities();
$this->dispatcher->addSubscriber($eventSubscriber);
$listeners = $this->dispatcher->getListeners('pre.foo');
$this->assertTrue($this->dispatcher->hasListeners(self::preFoo));
$this->assertCount(2, $listeners);
$this->assertInstanceOf('Symfony\Component\EventDispatcher\Tests\TestEventSubscriberWithPriorities', $listeners[0][0]);
}
public function testAddSubscriberWithMultipleListeners()
{
$eventSubscriber = new TestEventSubscriberWithMultipleListeners();
$this->dispatcher->addSubscriber($eventSubscriber);
$listeners = $this->dispatcher->getListeners('pre.foo');
$this->assertTrue($this->dispatcher->hasListeners(self::preFoo));
$this->assertCount(2, $listeners);
$this->assertEquals('preFoo2', $listeners[0][1]);
}
public function testRemoveSubscriber()
{
$eventSubscriber = new TestEventSubscriber();
$this->dispatcher->addSubscriber($eventSubscriber);
$this->assertTrue($this->dispatcher->hasListeners(self::preFoo));
$this->assertTrue($this->dispatcher->hasListeners(self::postFoo));
$this->dispatcher->removeSubscriber($eventSubscriber);
$this->assertFalse($this->dispatcher->hasListeners(self::preFoo));
$this->assertFalse($this->dispatcher->hasListeners(self::postFoo));
}
public function testRemoveSubscriberWithPriorities()
{
$eventSubscriber = new TestEventSubscriberWithPriorities();
$this->dispatcher->addSubscriber($eventSubscriber);
$this->assertTrue($this->dispatcher->hasListeners(self::preFoo));
$this->dispatcher->removeSubscriber($eventSubscriber);
$this->assertFalse($this->dispatcher->hasListeners(self::preFoo));
}
public function testRemoveSubscriberWithMultipleListeners()
{
$eventSubscriber = new TestEventSubscriberWithMultipleListeners();
$this->dispatcher->addSubscriber($eventSubscriber);
$this->assertTrue($this->dispatcher->hasListeners(self::preFoo));
$this->assertCount(2, $this->dispatcher->getListeners(self::preFoo));
$this->dispatcher->removeSubscriber($eventSubscriber);
$this->assertFalse($this->dispatcher->hasListeners(self::preFoo));
}
public function testEventReceivesTheDispatcherInstanceAsArgument()
{
$listener = new TestWithDispatcher();
$this->dispatcher->addListener('test', [$listener, 'foo']);
$this->assertNull($listener->name);
$this->assertNull($listener->dispatcher);
$this->dispatcher->dispatch(new Event(), 'test');
$this->assertEquals('test', $listener->name);
$this->assertSame($this->dispatcher, $listener->dispatcher);
}
/**
* @see https://bugs.php.net/62976
*
* This bug affects:
* - The PHP 5.3 branch for versions < 5.3.18
* - The PHP 5.4 branch for versions < 5.4.8
* - The PHP 5.5 branch is not affected
*/
public function testWorkaroundForPhpBug62976()
{
$dispatcher = $this->createEventDispatcher();
$dispatcher->addListener('bug.62976', new CallableClass());
$dispatcher->removeListener('bug.62976', function () {});
$this->assertTrue($dispatcher->hasListeners('bug.62976'));
}
public function testHasListenersWhenAddedCallbackListenerIsRemoved()
{
$listener = function () {};
$this->dispatcher->addListener('foo', $listener);
$this->dispatcher->removeListener('foo', $listener);
$this->assertFalse($this->dispatcher->hasListeners());
}
public function testGetListenersWhenAddedCallbackListenerIsRemoved()
{
$listener = function () {};
$this->dispatcher->addListener('foo', $listener);
$this->dispatcher->removeListener('foo', $listener);
$this->assertSame([], $this->dispatcher->getListeners());
}
public function testHasListenersWithoutEventsReturnsFalseAfterHasListenersWithEventHasBeenCalled()
{
$this->assertFalse($this->dispatcher->hasListeners('foo'));
$this->assertFalse($this->dispatcher->hasListeners());
}
public function testHasListenersIsLazy()
{
$called = 0;
$listener = [function () use (&$called) { ++$called; }, 'onFoo'];
$this->dispatcher->addListener('foo', $listener);
$this->assertTrue($this->dispatcher->hasListeners());
$this->assertTrue($this->dispatcher->hasListeners('foo'));
$this->assertSame(0, $called);
}
public function testDispatchLazyListener()
{
$called = 0;
$factory = function () use (&$called) {
++$called;
return new TestWithDispatcher();
};
$this->dispatcher->addListener('foo', [$factory, 'foo']);
$this->assertSame(0, $called);
$this->dispatcher->dispatch(new Event(), 'foo');
$this->dispatcher->dispatch(new Event(), 'foo');
$this->assertSame(1, $called);
}
public function testRemoveFindsLazyListeners()
{
$test = new TestWithDispatcher();
$factory = function () use ($test) { return $test; };
$this->dispatcher->addListener('foo', [$factory, 'foo']);
$this->assertTrue($this->dispatcher->hasListeners('foo'));
$this->dispatcher->removeListener('foo', [$test, 'foo']);
$this->assertFalse($this->dispatcher->hasListeners('foo'));
$this->dispatcher->addListener('foo', [$test, 'foo']);
$this->assertTrue($this->dispatcher->hasListeners('foo'));
$this->dispatcher->removeListener('foo', [$factory, 'foo']);
$this->assertFalse($this->dispatcher->hasListeners('foo'));
}
public function testPriorityFindsLazyListeners()
{
$test = new TestWithDispatcher();
$factory = function () use ($test) { return $test; };
$this->dispatcher->addListener('foo', [$factory, 'foo'], 3);
$this->assertSame(3, $this->dispatcher->getListenerPriority('foo', [$test, 'foo']));
$this->dispatcher->removeListener('foo', [$factory, 'foo']);
$this->dispatcher->addListener('foo', [$test, 'foo'], 5);
$this->assertSame(5, $this->dispatcher->getListenerPriority('foo', [$factory, 'foo']));
}
public function testGetLazyListeners()
{
$test = new TestWithDispatcher();
$factory = function () use ($test) { return $test; };
$this->dispatcher->addListener('foo', [$factory, 'foo'], 3);
$this->assertSame([[$test, 'foo']], $this->dispatcher->getListeners('foo'));
$this->dispatcher->removeListener('foo', [$test, 'foo']);
$this->dispatcher->addListener('bar', [$factory, 'foo'], 3);
$this->assertSame(['bar' => [[$test, 'foo']]], $this->dispatcher->getListeners());
}
public function testMutatingWhilePropagationIsStopped()
{
$testLoaded = false;
$test = new TestEventListener();
$this->dispatcher->addListener('foo', [$test, 'postFoo']);
$this->dispatcher->addListener('foo', [function () use ($test, &$testLoaded) {
$testLoaded = true;
return $test;
}, 'preFoo']);
$this->dispatcher->dispatch(new Event(), 'foo');
$this->assertTrue($test->postFooInvoked);
$this->assertFalse($test->preFooInvoked);
$this->assertsame(0, $this->dispatcher->getListenerPriority('foo', [$test, 'preFoo']));
$test->preFoo(new Event());
$this->dispatcher->dispatch(new Event(), 'foo');
$this->assertTrue($testLoaded);
}
/**
* @group legacy
* @expectedDeprecation Calling the "Symfony\Component\EventDispatcher\EventDispatcherInterface::dispatch()" method with the event name as the first argument is deprecated since Symfony 4.3, pass it as the second argument and provide the event object as the first argument instead.
*/
public function testLegacySignatureWithoutEvent()
{
$this->dispatcher->dispatch('foo');
}
/**
* @group legacy
* @expectedDeprecation Calling the "Symfony\Component\EventDispatcher\EventDispatcherInterface::dispatch()" method with the event name as the first argument is deprecated since Symfony 4.3, pass it as the second argument and provide the event object as the first argument instead.
*/
public function testLegacySignatureWithEvent()
{
$this->dispatcher->dispatch('foo', new Event());
}
public function testLegacySignatureWithNewEventObject()
{
$this->expectException('TypeError');
$this->expectExceptionMessage('Argument 1 passed to "Symfony\Component\EventDispatcher\EventDispatcherInterface::dispatch()" must be an object, string given.');
$this->dispatcher->dispatch('foo', new ContractsEvent());
}
}
class CallableClass
{
public function __invoke()
{
}
}
class TestEventListener
{
public $preFooInvoked = false;
public $postFooInvoked = false;
/* Listener methods */
public function preFoo($e)
{
$this->preFooInvoked = true;
}
public function postFoo($e)
{
$this->postFooInvoked = true;
if (!$this->preFooInvoked) {
$e->stopPropagation();
}
}
}
class TestWithDispatcher
{
public $name;
public $dispatcher;
public function foo($e, $name, $dispatcher)
{
$this->name = $name;
$this->dispatcher = $dispatcher;
}
}
class TestEventSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return ['pre.foo' => 'preFoo', 'post.foo' => 'postFoo'];
}
}
class TestEventSubscriberWithPriorities implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return [
'pre.foo' => ['preFoo', 10],
'post.foo' => ['postFoo'],
];
}
}
class TestEventSubscriberWithMultipleListeners implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return ['pre.foo' => [
['preFoo1'],
['preFoo2', 10],
]];
}
}

55
addons/weliam_smartcity/vendor/symfony/event-dispatcher/Tests/EventTest.php

@ -0,0 +1,55 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\EventDispatcher\Tests;
use PHPUnit\Framework\TestCase;
use Symfony\Component\EventDispatcher\Event;
/**
* @group legacy
*/
class EventTest extends TestCase
{
/**
* @var \Symfony\Component\EventDispatcher\Event
*/
protected $event;
/**
* Sets up the fixture, for example, opens a network connection.
* This method is called before a test is executed.
*/
protected function setUp(): void
{
$this->event = new Event();
}
/**
* Tears down the fixture, for example, closes a network connection.
* This method is called after a test is executed.
*/
protected function tearDown(): void
{
$this->event = null;
}
public function testIsPropagationStopped()
{
$this->assertFalse($this->event->isPropagationStopped());
}
public function testStopPropagationAndIsPropagationStopped()
{
$this->event->stopPropagation();
$this->assertTrue($this->event->isPropagationStopped());
}
}

134
addons/weliam_smartcity/vendor/symfony/event-dispatcher/Tests/GenericEventTest.php

@ -0,0 +1,134 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\EventDispatcher\Tests;
use PHPUnit\Framework\TestCase;
use Symfony\Component\EventDispatcher\GenericEvent;
/**
* Test class for Event.
*/
class GenericEventTest extends TestCase
{
/**
* @var GenericEvent
*/
private $event;
private $subject;
/**
* Prepares the environment before running a test.
*/
protected function setUp(): void
{
$this->subject = new \stdClass();
$this->event = new GenericEvent($this->subject, ['name' => 'Event']);
}
/**
* Cleans up the environment after running a test.
*/
protected function tearDown(): void
{
$this->subject = null;
$this->event = null;
}
public function testConstruct()
{
$this->assertEquals($this->event, new GenericEvent($this->subject, ['name' => 'Event']));
}
/**
* Tests Event->getArgs().
*/
public function testGetArguments()
{
// test getting all
$this->assertSame(['name' => 'Event'], $this->event->getArguments());
}
public function testSetArguments()
{
$result = $this->event->setArguments(['foo' => 'bar']);
$this->assertSame(['foo' => 'bar'], $this->event->getArguments());
$this->assertSame($this->event, $result);
}
public function testSetArgument()
{
$result = $this->event->setArgument('foo2', 'bar2');
$this->assertSame(['name' => 'Event', 'foo2' => 'bar2'], $this->event->getArguments());
$this->assertEquals($this->event, $result);
}
public function testGetArgument()
{
// test getting key
$this->assertEquals('Event', $this->event->getArgument('name'));
}
public function testGetArgException()
{
$this->expectException('\InvalidArgumentException');
$this->event->getArgument('nameNotExist');
}
public function testOffsetGet()
{
// test getting key
$this->assertEquals('Event', $this->event['name']);
// test getting invalid arg
$this->expectException('InvalidArgumentException');
$this->assertFalse($this->event['nameNotExist']);
}
public function testOffsetSet()
{
$this->event['foo2'] = 'bar2';
$this->assertSame(['name' => 'Event', 'foo2' => 'bar2'], $this->event->getArguments());
}
public function testOffsetUnset()
{
unset($this->event['name']);
$this->assertSame([], $this->event->getArguments());
}
public function testOffsetIsset()
{
$this->assertArrayHasKey('name', $this->event);
$this->assertArrayNotHasKey('nameNotExist', $this->event);
}
public function testHasArgument()
{
$this->assertTrue($this->event->hasArgument('name'));
$this->assertFalse($this->event->hasArgument('nameNotExist'));
}
public function testGetSubject()
{
$this->assertSame($this->subject, $this->event->getSubject());
}
public function testHasIterator()
{
$data = [];
foreach ($this->event as $key => $value) {
$data[$key] = $value;
}
$this->assertEquals(['name' => 'Event'], $data);
}
}

100
addons/weliam_smartcity/vendor/symfony/event-dispatcher/Tests/ImmutableEventDispatcherTest.php

@ -0,0 +1,100 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\EventDispatcher\Tests;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\EventDispatcher\ImmutableEventDispatcher;
/**
* @author Bernhard Schussek <bschussek@gmail.com>
*/
class ImmutableEventDispatcherTest extends TestCase
{
/**
* @var MockObject
*/
private $innerDispatcher;
/**
* @var ImmutableEventDispatcher
*/
private $dispatcher;
protected function setUp(): void
{
$this->innerDispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')->getMock();
$this->dispatcher = new ImmutableEventDispatcher($this->innerDispatcher);
}
public function testDispatchDelegates()
{
$event = new Event();
$resultEvent = new Event();
$this->innerDispatcher->expects($this->once())
->method('dispatch')
->with($event, 'event')
->willReturn($resultEvent);
$this->assertSame($resultEvent, $this->dispatcher->dispatch('event', $event));
}
public function testGetListenersDelegates()
{
$this->innerDispatcher->expects($this->once())
->method('getListeners')
->with('event')
->willReturn(['result']);
$this->assertSame(['result'], $this->dispatcher->getListeners('event'));
}
public function testHasListenersDelegates()
{
$this->innerDispatcher->expects($this->once())
->method('hasListeners')
->with('event')
->willReturn(true);
$this->assertTrue($this->dispatcher->hasListeners('event'));
}
public function testAddListenerDisallowed()
{
$this->expectException('\BadMethodCallException');
$this->dispatcher->addListener('event', function () { return 'foo'; });
}
public function testAddSubscriberDisallowed()
{
$this->expectException('\BadMethodCallException');
$subscriber = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventSubscriberInterface')->getMock();
$this->dispatcher->addSubscriber($subscriber);
}
public function testRemoveListenerDisallowed()
{
$this->expectException('\BadMethodCallException');
$this->dispatcher->removeListener('event', function () { return 'foo'; });
}
public function testRemoveSubscriberDisallowed()
{
$this->expectException('\BadMethodCallException');
$subscriber = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventSubscriberInterface')->getMock();
$this->dispatcher->removeSubscriber($subscriber);
}
}

63
addons/weliam_smartcity/vendor/symfony/event-dispatcher/Tests/LegacyEventDispatcherTest.php

@ -0,0 +1,63 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\EventDispatcher\Tests;
use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\EventDispatcher\LegacyEventDispatcherProxy;
use Symfony\Contracts\EventDispatcher\Event as ContractsEvent;
/**
* @group legacy
*/
class LegacyEventDispatcherTest extends EventDispatcherTest
{
/**
* @group legacy
* @expectedDeprecation The signature of the "Symfony\Component\EventDispatcher\Tests\TestLegacyEventDispatcher::dispatch()" method should be updated to "dispatch($event, string $eventName = null)", not doing so is deprecated since Symfony 4.3.
* @expectedDeprecation Calling the "Symfony\Contracts\EventDispatcher\EventDispatcherInterface::dispatch()" method with the event name as the first argument is deprecated since Symfony 4.3, pass it as the second argument and provide the event object as the first argument instead.
*/
public function testLegacySignatureWithoutEvent()
{
$this->createEventDispatcher()->dispatch('foo');
}
/**
* @group legacy
* @expectedDeprecation The signature of the "Symfony\Component\EventDispatcher\Tests\TestLegacyEventDispatcher::dispatch()" method should be updated to "dispatch($event, string $eventName = null)", not doing so is deprecated since Symfony 4.3.
* @expectedDeprecation Calling the "Symfony\Contracts\EventDispatcher\EventDispatcherInterface::dispatch()" method with the event name as the first argument is deprecated since Symfony 4.3, pass it as the second argument and provide the event object as the first argument instead.
*/
public function testLegacySignatureWithEvent()
{
$this->createEventDispatcher()->dispatch('foo', new Event());
}
public function testLegacySignatureWithNewEventObject()
{
$this->expectException('TypeError');
$this->expectExceptionMessage('Argument 1 passed to "Symfony\Contracts\EventDispatcher\EventDispatcherInterface::dispatch()" must be an object, string given.');
$this->createEventDispatcher()->dispatch('foo', new ContractsEvent());
}
protected function createEventDispatcher()
{
return LegacyEventDispatcherProxy::decorate(new TestLegacyEventDispatcher());
}
}
class TestLegacyEventDispatcher extends EventDispatcher
{
public function dispatch($eventName, Event $event = null)
{
return parent::dispatch($event, $eventName);
}
}

54
addons/weliam_smartcity/vendor/symfony/event-dispatcher/composer.json

@ -0,0 +1,54 @@
{
"name": "symfony/event-dispatcher",
"type": "library",
"description": "Symfony EventDispatcher Component",
"keywords": [],
"homepage": "https://symfony.com",
"license": "MIT",
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"require": {
"php": "^7.1.3",
"symfony/event-dispatcher-contracts": "^1.1"
},
"require-dev": {
"symfony/dependency-injection": "~3.4|~4.0",
"symfony/expression-language": "~3.4|~4.0",
"symfony/config": "~3.4|~4.0",
"symfony/http-foundation": "^3.4|^4.0",
"symfony/service-contracts": "^1.1",
"symfony/stopwatch": "~3.4|~4.0",
"psr/log": "~1.0"
},
"conflict": {
"symfony/dependency-injection": "<3.4"
},
"provide": {
"psr/event-dispatcher-implementation": "1.0",
"symfony/event-dispatcher-implementation": "1.1"
},
"suggest": {
"symfony/dependency-injection": "",
"symfony/http-kernel": ""
},
"autoload": {
"psr-4": { "Symfony\\Component\\EventDispatcher\\": "" },
"exclude-from-classmap": [
"/Tests/"
]
},
"minimum-stability": "dev",
"extra": {
"branch-alias": {
"dev-master": "4.3-dev"
}
}
}

31
addons/weliam_smartcity/vendor/symfony/event-dispatcher/phpunit.xml.dist

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/5.2/phpunit.xsd"
backupGlobals="false"
colors="true"
bootstrap="vendor/autoload.php"
failOnRisky="true"
failOnWarning="true"
>
<php>
<ini name="error_reporting" value="-1" />
</php>
<testsuites>
<testsuite name="Symfony EventDispatcher Component Test Suite">
<directory>./Tests/</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory>./</directory>
<exclude>
<directory>./Resources</directory>
<directory>./Tests</directory>
<directory>./vendor</directory>
</exclude>
</whitelist>
</filter>
</phpunit>

3
addons/weliam_smartcity/vendor/symfony/mime/.gitignore

@ -0,0 +1,3 @@
composer.lock
phpunit.xml
vendor/

98
addons/weliam_smartcity/vendor/symfony/mime/Address.php

@ -0,0 +1,98 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime;
use Egulias\EmailValidator\EmailValidator;
use Egulias\EmailValidator\Validation\RFCValidation;
use Symfony\Component\Mime\Encoder\IdnAddressEncoder;
use Symfony\Component\Mime\Exception\InvalidArgumentException;
use Symfony\Component\Mime\Exception\LogicException;
use Symfony\Component\Mime\Exception\RfcComplianceException;
/**
* @author Fabien Potencier <fabien@symfony.com>
*
* @experimental in 4.3
*/
class Address
{
private static $validator;
private static $encoder;
private $address;
public function __construct(string $address)
{
if (!class_exists(EmailValidator::class)) {
throw new LogicException(sprintf('The "%s" class cannot be used as it needs "%s"; try running "composer require egulias/email-validator".', __CLASS__, EmailValidator::class));
}
if (null === self::$validator) {
self::$validator = new EmailValidator();
}
$this->address = trim($address);
if (!self::$validator->isValid($this->address, new RFCValidation())) {
throw new RfcComplianceException(sprintf('Email "%s" does not comply with addr-spec of RFC 2822.', $address));
}
}
public function getAddress(): string
{
return $this->address;
}
public function getEncodedAddress(): string
{
if (null === self::$encoder) {
self::$encoder = new IdnAddressEncoder();
}
return self::$encoder->encodeString($this->address);
}
public function toString(): string
{
return $this->getEncodedAddress();
}
/**
* @param Address|string $address
*/
public static function create($address): self
{
if ($address instanceof self) {
return $address;
}
if (\is_string($address)) {
return new self($address);
}
throw new InvalidArgumentException(sprintf('An address can be an instance of Address or a string ("%s") given).', \is_object($address) ? \get_class($address) : \gettype($address)));
}
/**
* @param (Address|string)[] $addresses
*
* @return Address[]
*/
public static function createArray(array $addresses): array
{
$addrs = [];
foreach ($addresses as $address) {
$addrs[] = self::create($address);
}
return $addrs;
}
}

22
addons/weliam_smartcity/vendor/symfony/mime/BodyRendererInterface.php

@ -0,0 +1,22 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime;
/**
* @author Fabien Potencier <fabien@symfony.com>
*
* @experimental in 4.3
*/
interface BodyRendererInterface
{
public function render(Message $message): void;
}

12
addons/weliam_smartcity/vendor/symfony/mime/CHANGELOG.md

@ -0,0 +1,12 @@
CHANGELOG
=========
4.3.3
-----
* [BC BREAK] Renamed method `Headers::getAll()` to `Headers::all()`.
4.3.0
-----
* Introduced the component as experimental

224
addons/weliam_smartcity/vendor/symfony/mime/CharacterStream.php

@ -0,0 +1,224 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime;
/**
* @author Fabien Potencier <fabien@symfony.com>
* @author Xavier De Cock <xdecock@gmail.com>
*
* @internal
*
* @experimental in 4.3
*/
final class CharacterStream
{
/** Pre-computed for optimization */
private const UTF8_LENGTH_MAP = [
"\x00" => 1, "\x01" => 1, "\x02" => 1, "\x03" => 1, "\x04" => 1, "\x05" => 1, "\x06" => 1, "\x07" => 1,
"\x08" => 1, "\x09" => 1, "\x0a" => 1, "\x0b" => 1, "\x0c" => 1, "\x0d" => 1, "\x0e" => 1, "\x0f" => 1,
"\x10" => 1, "\x11" => 1, "\x12" => 1, "\x13" => 1, "\x14" => 1, "\x15" => 1, "\x16" => 1, "\x17" => 1,
"\x18" => 1, "\x19" => 1, "\x1a" => 1, "\x1b" => 1, "\x1c" => 1, "\x1d" => 1, "\x1e" => 1, "\x1f" => 1,
"\x20" => 1, "\x21" => 1, "\x22" => 1, "\x23" => 1, "\x24" => 1, "\x25" => 1, "\x26" => 1, "\x27" => 1,
"\x28" => 1, "\x29" => 1, "\x2a" => 1, "\x2b" => 1, "\x2c" => 1, "\x2d" => 1, "\x2e" => 1, "\x2f" => 1,
"\x30" => 1, "\x31" => 1, "\x32" => 1, "\x33" => 1, "\x34" => 1, "\x35" => 1, "\x36" => 1, "\x37" => 1,
"\x38" => 1, "\x39" => 1, "\x3a" => 1, "\x3b" => 1, "\x3c" => 1, "\x3d" => 1, "\x3e" => 1, "\x3f" => 1,
"\x40" => 1, "\x41" => 1, "\x42" => 1, "\x43" => 1, "\x44" => 1, "\x45" => 1, "\x46" => 1, "\x47" => 1,
"\x48" => 1, "\x49" => 1, "\x4a" => 1, "\x4b" => 1, "\x4c" => 1, "\x4d" => 1, "\x4e" => 1, "\x4f" => 1,
"\x50" => 1, "\x51" => 1, "\x52" => 1, "\x53" => 1, "\x54" => 1, "\x55" => 1, "\x56" => 1, "\x57" => 1,
"\x58" => 1, "\x59" => 1, "\x5a" => 1, "\x5b" => 1, "\x5c" => 1, "\x5d" => 1, "\x5e" => 1, "\x5f" => 1,
"\x60" => 1, "\x61" => 1, "\x62" => 1, "\x63" => 1, "\x64" => 1, "\x65" => 1, "\x66" => 1, "\x67" => 1,
"\x68" => 1, "\x69" => 1, "\x6a" => 1, "\x6b" => 1, "\x6c" => 1, "\x6d" => 1, "\x6e" => 1, "\x6f" => 1,
"\x70" => 1, "\x71" => 1, "\x72" => 1, "\x73" => 1, "\x74" => 1, "\x75" => 1, "\x76" => 1, "\x77" => 1,
"\x78" => 1, "\x79" => 1, "\x7a" => 1, "\x7b" => 1, "\x7c" => 1, "\x7d" => 1, "\x7e" => 1, "\x7f" => 1,
"\x80" => 0, "\x81" => 0, "\x82" => 0, "\x83" => 0, "\x84" => 0, "\x85" => 0, "\x86" => 0, "\x87" => 0,
"\x88" => 0, "\x89" => 0, "\x8a" => 0, "\x8b" => 0, "\x8c" => 0, "\x8d" => 0, "\x8e" => 0, "\x8f" => 0,
"\x90" => 0, "\x91" => 0, "\x92" => 0, "\x93" => 0, "\x94" => 0, "\x95" => 0, "\x96" => 0, "\x97" => 0,
"\x98" => 0, "\x99" => 0, "\x9a" => 0, "\x9b" => 0, "\x9c" => 0, "\x9d" => 0, "\x9e" => 0, "\x9f" => 0,
"\xa0" => 0, "\xa1" => 0, "\xa2" => 0, "\xa3" => 0, "\xa4" => 0, "\xa5" => 0, "\xa6" => 0, "\xa7" => 0,
"\xa8" => 0, "\xa9" => 0, "\xaa" => 0, "\xab" => 0, "\xac" => 0, "\xad" => 0, "\xae" => 0, "\xaf" => 0,
"\xb0" => 0, "\xb1" => 0, "\xb2" => 0, "\xb3" => 0, "\xb4" => 0, "\xb5" => 0, "\xb6" => 0, "\xb7" => 0,
"\xb8" => 0, "\xb9" => 0, "\xba" => 0, "\xbb" => 0, "\xbc" => 0, "\xbd" => 0, "\xbe" => 0, "\xbf" => 0,
"\xc0" => 2, "\xc1" => 2, "\xc2" => 2, "\xc3" => 2, "\xc4" => 2, "\xc5" => 2, "\xc6" => 2, "\xc7" => 2,
"\xc8" => 2, "\xc9" => 2, "\xca" => 2, "\xcb" => 2, "\xcc" => 2, "\xcd" => 2, "\xce" => 2, "\xcf" => 2,
"\xd0" => 2, "\xd1" => 2, "\xd2" => 2, "\xd3" => 2, "\xd4" => 2, "\xd5" => 2, "\xd6" => 2, "\xd7" => 2,
"\xd8" => 2, "\xd9" => 2, "\xda" => 2, "\xdb" => 2, "\xdc" => 2, "\xdd" => 2, "\xde" => 2, "\xdf" => 2,
"\xe0" => 3, "\xe1" => 3, "\xe2" => 3, "\xe3" => 3, "\xe4" => 3, "\xe5" => 3, "\xe6" => 3, "\xe7" => 3,
"\xe8" => 3, "\xe9" => 3, "\xea" => 3, "\xeb" => 3, "\xec" => 3, "\xed" => 3, "\xee" => 3, "\xef" => 3,
"\xf0" => 4, "\xf1" => 4, "\xf2" => 4, "\xf3" => 4, "\xf4" => 4, "\xf5" => 4, "\xf6" => 4, "\xf7" => 4,
"\xf8" => 5, "\xf9" => 5, "\xfa" => 5, "\xfb" => 5, "\xfc" => 6, "\xfd" => 6, "\xfe" => 0, "\xff" => 0,
];
private $data = '';
private $dataSize = 0;
private $map = [];
private $charCount = 0;
private $currentPos = 0;
private $fixedWidth = 0;
/**
* @param resource|string $input
*/
public function __construct($input, ?string $charset = 'utf-8')
{
$charset = strtolower(trim($charset)) ?: 'utf-8';
if ('utf-8' === $charset || 'utf8' === $charset) {
$this->fixedWidth = 0;
$this->map = ['p' => [], 'i' => []];
} else {
switch ($charset) {
// 16 bits
case 'ucs2':
case 'ucs-2':
case 'utf16':
case 'utf-16':
$this->fixedWidth = 2;
break;
// 32 bits
case 'ucs4':
case 'ucs-4':
case 'utf32':
case 'utf-32':
$this->fixedWidth = 4;
break;
// 7-8 bit charsets: (us-)?ascii, (iso|iec)-?8859-?[0-9]+, windows-?125[0-9], cp-?[0-9]+, ansi, macintosh,
// koi-?7, koi-?8-?.+, mik, (cork|t1), v?iscii
// and fallback
default:
$this->fixedWidth = 1;
}
}
if (\is_resource($input)) {
$blocks = 512;
if (stream_get_meta_data($input)['seekable'] ?? false) {
rewind($input);
}
while (false !== $read = fread($input, $blocks)) {
$this->write($read);
}
} else {
$this->write($input);
}
}
public function read(int $length): ?string
{
if ($this->currentPos >= $this->charCount) {
return null;
}
$ret = null;
$length = ($this->currentPos + $length > $this->charCount) ? $this->charCount - $this->currentPos : $length;
if ($this->fixedWidth > 0) {
$len = $length * $this->fixedWidth;
$ret = substr($this->data, $this->currentPos * $this->fixedWidth, $len);
$this->currentPos += $length;
} else {
$end = $this->currentPos + $length;
$end = $end > $this->charCount ? $this->charCount : $end;
$ret = '';
$start = 0;
if ($this->currentPos > 0) {
$start = $this->map['p'][$this->currentPos - 1];
}
$to = $start;
for (; $this->currentPos < $end; ++$this->currentPos) {
if (isset($this->map['i'][$this->currentPos])) {
$ret .= substr($this->data, $start, $to - $start).'?';
$start = $this->map['p'][$this->currentPos];
} else {
$to = $this->map['p'][$this->currentPos];
}
}
$ret .= substr($this->data, $start, $to - $start);
}
return $ret;
}
public function readBytes(int $length): ?array
{
if (null !== $read = $this->read($length)) {
return array_map('ord', str_split($read, 1));
}
return null;
}
public function setPointer(int $charOffset): void
{
if ($this->charCount < $charOffset) {
$charOffset = $this->charCount;
}
$this->currentPos = $charOffset;
}
public function write(string $chars): void
{
$ignored = '';
$this->data .= $chars;
if ($this->fixedWidth > 0) {
$strlen = \strlen($chars);
$ignoredL = $strlen % $this->fixedWidth;
$ignored = $ignoredL ? substr($chars, -$ignoredL) : '';
$this->charCount += ($strlen - $ignoredL) / $this->fixedWidth;
} else {
$this->charCount += $this->getUtf8CharPositions($chars, $this->dataSize, $ignored);
}
$this->dataSize = \strlen($this->data) - \strlen($ignored);
}
private function getUtf8CharPositions(string $string, int $startOffset, &$ignoredChars): int
{
$strlen = \strlen($string);
$charPos = \count($this->map['p']);
$foundChars = 0;
$invalid = false;
for ($i = 0; $i < $strlen; ++$i) {
$char = $string[$i];
$size = self::UTF8_LENGTH_MAP[$char];
if (0 == $size) {
/* char is invalid, we must wait for a resync */
$invalid = true;
continue;
}
if ($invalid) {
/* We mark the chars as invalid and start a new char */
$this->map['p'][$charPos + $foundChars] = $startOffset + $i;
$this->map['i'][$charPos + $foundChars] = true;
++$foundChars;
$invalid = false;
}
if (($i + $size) > $strlen) {
$ignoredChars = substr($string, $i);
break;
}
for ($j = 1; $j < $size; ++$j) {
$char = $string[$i + $j];
if ($char > "\x7F" && $char < "\xC0") {
// Valid - continue parsing
} else {
/* char is invalid, we must wait for a resync */
$invalid = true;
continue 2;
}
}
/* Ok we got a complete char here */
$this->map['p'][$charPos + $foundChars] = $startOffset + $i + $size;
$i += $j - 1;
++$foundChars;
}
return $foundChars;
}
}

48
addons/weliam_smartcity/vendor/symfony/mime/DependencyInjection/AddMimeTypeGuesserPass.php

@ -0,0 +1,48 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime\DependencyInjection;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
/**
* Registers custom mime types guessers.
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @experimental in 4.3
*/
class AddMimeTypeGuesserPass implements CompilerPassInterface
{
private $mimeTypesService;
private $mimeTypeGuesserTag;
public function __construct(string $mimeTypesService = 'mime_types', string $mimeTypeGuesserTag = 'mime.mime_type_guesser')
{
$this->mimeTypesService = $mimeTypesService;
$this->mimeTypeGuesserTag = $mimeTypeGuesserTag;
}
/**
* {@inheritdoc}
*/
public function process(ContainerBuilder $container)
{
if ($container->has($this->mimeTypesService)) {
$definition = $container->findDefinition($this->mimeTypesService);
foreach ($container->findTaggedServiceIds($this->mimeTypeGuesserTag, true) as $id => $attributes) {
$definition->addMethodCall('registerGuesser', [new Reference($id)]);
}
}
}
}

593
addons/weliam_smartcity/vendor/symfony/mime/Email.php

@ -0,0 +1,593 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime;
use Symfony\Component\Mime\Exception\LogicException;
use Symfony\Component\Mime\Part\AbstractPart;
use Symfony\Component\Mime\Part\DataPart;
use Symfony\Component\Mime\Part\Multipart\AlternativePart;
use Symfony\Component\Mime\Part\Multipart\MixedPart;
use Symfony\Component\Mime\Part\Multipart\RelatedPart;
use Symfony\Component\Mime\Part\TextPart;
/**
* @author Fabien Potencier <fabien@symfony.com>
*
* @experimental in 4.3
*/
class Email extends Message
{
const PRIORITY_HIGHEST = 1;
const PRIORITY_HIGH = 2;
const PRIORITY_NORMAL = 3;
const PRIORITY_LOW = 4;
const PRIORITY_LOWEST = 5;
private const PRIORITY_MAP = [
self::PRIORITY_HIGHEST => 'Highest',
self::PRIORITY_HIGH => 'High',
self::PRIORITY_NORMAL => 'Normal',
self::PRIORITY_LOW => 'Low',
self::PRIORITY_LOWEST => 'Lowest',
];
private $text;
private $textCharset;
private $html;
private $htmlCharset;
private $attachments = [];
/**
* @return $this
*/
public function subject(string $subject)
{
return $this->setHeaderBody('Text', 'Subject', $subject);
}
public function getSubject(): ?string
{
return $this->getHeaders()->getHeaderBody('Subject');
}
/**
* @return $this
*/
public function date(\DateTimeInterface $dateTime)
{
return $this->setHeaderBody('Date', 'Date', $dateTime);
}
public function getDate(): ?\DateTimeImmutable
{
return $this->getHeaders()->getHeaderBody('Date');
}
/**
* @param Address|string $address
*
* @return $this
*/
public function returnPath($address)
{
return $this->setHeaderBody('Path', 'Return-Path', Address::create($address));
}
public function getReturnPath(): ?Address
{
return $this->getHeaders()->getHeaderBody('Return-Path');
}
/**
* @param Address|string $address
*
* @return $this
*/
public function sender($address)
{
return $this->setHeaderBody('Mailbox', 'Sender', Address::create($address));
}
public function getSender(): ?Address
{
return $this->getHeaders()->getHeaderBody('Sender');
}
/**
* @param Address|NamedAddress|string ...$addresses
*
* @return $this
*/
public function addFrom(...$addresses)
{
return $this->addListAddressHeaderBody('From', $addresses);
}
/**
* @param Address|NamedAddress|string ...$addresses
*
* @return $this
*/
public function from(...$addresses)
{
return $this->setListAddressHeaderBody('From', $addresses);
}
/**
* @return (Address|NamedAddress)[]
*/
public function getFrom(): array
{
return $this->getHeaders()->getHeaderBody('From') ?: [];
}
/**
* @param Address|string ...$addresses
*
* @return $this
*/
public function addReplyTo(...$addresses)
{
return $this->addListAddressHeaderBody('Reply-To', $addresses);
}
/**
* @param Address|string ...$addresses
*
* @return $this
*/
public function replyTo(...$addresses)
{
return $this->setListAddressHeaderBody('Reply-To', $addresses);
}
/**
* @return Address[]
*/
public function getReplyTo(): array
{
return $this->getHeaders()->getHeaderBody('Reply-To') ?: [];
}
/**
* @param Address|NamedAddress|string ...$addresses
*
* @return $this
*/
public function addTo(...$addresses)
{
return $this->addListAddressHeaderBody('To', $addresses);
}
/**
* @param Address|NamedAddress|string ...$addresses
*
* @return $this
*/
public function to(...$addresses)
{
return $this->setListAddressHeaderBody('To', $addresses);
}
/**
* @return (Address|NamedAddress)[]
*/
public function getTo(): array
{
return $this->getHeaders()->getHeaderBody('To') ?: [];
}
/**
* @param Address|NamedAddress|string ...$addresses
*
* @return $this
*/
public function addCc(...$addresses)
{
return $this->addListAddressHeaderBody('Cc', $addresses);
}
/**
* @param Address|string ...$addresses
*
* @return $this
*/
public function cc(...$addresses)
{
return $this->setListAddressHeaderBody('Cc', $addresses);
}
/**
* @return (Address|NamedAddress)[]
*/
public function getCc(): array
{
return $this->getHeaders()->getHeaderBody('Cc') ?: [];
}
/**
* @param Address|NamedAddress|string ...$addresses
*
* @return $this
*/
public function addBcc(...$addresses)
{
return $this->addListAddressHeaderBody('Bcc', $addresses);
}
/**
* @param Address|string ...$addresses
*
* @return $this
*/
public function bcc(...$addresses)
{
return $this->setListAddressHeaderBody('Bcc', $addresses);
}
/**
* @return (Address|NamedAddress)[]
*/
public function getBcc(): array
{
return $this->getHeaders()->getHeaderBody('Bcc') ?: [];
}
/**
* Sets the priority of this message.
*
* The value is an integer where 1 is the highest priority and 5 is the lowest.
*
* @return $this
*/
public function priority(int $priority)
{
if ($priority > 5) {
$priority = 5;
} elseif ($priority < 1) {
$priority = 1;
}
return $this->setHeaderBody('Text', 'X-Priority', sprintf('%d (%s)', $priority, self::PRIORITY_MAP[$priority]));
}
/**
* Get the priority of this message.
*
* The returned value is an integer where 1 is the highest priority and 5
* is the lowest.
*/
public function getPriority(): int
{
list($priority) = sscanf($this->getHeaders()->getHeaderBody('X-Priority'), '%[1-5]');
return $priority ?? 3;
}
/**
* @param resource|string $body
*
* @return $this
*/
public function text($body, string $charset = 'utf-8')
{
$this->text = $body;
$this->textCharset = $charset;
return $this;
}
/**
* @return resource|string|null
*/
public function getTextBody()
{
return $this->text;
}
public function getTextCharset(): ?string
{
return $this->textCharset;
}
/**
* @param resource|string|null $body
*
* @return $this
*/
public function html($body, string $charset = 'utf-8')
{
$this->html = $body;
$this->htmlCharset = $charset;
return $this;
}
/**
* @return resource|string|null
*/
public function getHtmlBody()
{
return $this->html;
}
public function getHtmlCharset(): ?string
{
return $this->htmlCharset;
}
/**
* @param resource|string $body
*
* @return $this
*/
public function attach($body, string $name = null, string $contentType = null)
{
$this->attachments[] = ['body' => $body, 'name' => $name, 'content-type' => $contentType, 'inline' => false];
return $this;
}
/**
* @return $this
*/
public function attachFromPath(string $path, string $name = null, string $contentType = null)
{
$this->attachments[] = ['path' => $path, 'name' => $name, 'content-type' => $contentType, 'inline' => false];
return $this;
}
/**
* @param resource|string $body
*
* @return $this
*/
public function embed($body, string $name = null, string $contentType = null)
{
$this->attachments[] = ['body' => $body, 'name' => $name, 'content-type' => $contentType, 'inline' => true];
return $this;
}
/**
* @return $this
*/
public function embedFromPath(string $path, string $name = null, string $contentType = null)
{
$this->attachments[] = ['path' => $path, 'name' => $name, 'content-type' => $contentType, 'inline' => true];
return $this;
}
/**
* @return $this
*/
public function attachPart(DataPart $part)
{
$this->attachments[] = ['part' => $part];
return $this;
}
/**
* @return DataPart[]
*/
public function getAttachments(): array
{
$parts = [];
foreach ($this->attachments as $attachment) {
$parts[] = $this->createDataPart($attachment);
}
return $parts;
}
public function getBody(): AbstractPart
{
if (null !== $body = parent::getBody()) {
return $body;
}
return $this->generateBody();
}
/**
* Generates an AbstractPart based on the raw body of a message.
*
* The most "complex" part generated by this method is when there is text and HTML bodies
* with related images for the HTML part and some attachments:
*
* multipart/mixed
* |
* |------------> multipart/related
* | |
* | |------------> multipart/alternative
* | | |
* | | ------------> text/plain (with content)
* | | |
* | | ------------> text/html (with content)
* | |
* | ------------> image/png (with content)
* |
* ------------> application/pdf (with content)
*/
private function generateBody(): AbstractPart
{
[$htmlPart, $attachmentParts, $inlineParts] = $this->prepareParts();
if (null === $this->text && null === $this->html && !$attachmentParts) {
throw new LogicException('A message must have a text or an HTML part or attachments.');
}
$part = null === $this->text ? null : new TextPart($this->text, $this->textCharset);
if (null !== $htmlPart) {
if (null !== $part) {
$part = new AlternativePart($part, $htmlPart);
} else {
$part = $htmlPart;
}
}
if ($inlineParts) {
$part = new RelatedPart($part, ...$inlineParts);
}
if ($attachmentParts) {
if ($part) {
$part = new MixedPart($part, ...$attachmentParts);
} else {
$part = new MixedPart(...$attachmentParts);
}
}
return $part;
}
private function prepareParts(): ?array
{
$names = [];
$htmlPart = null;
$html = $this->html;
if (null !== $this->html) {
if (\is_resource($html)) {
if (stream_get_meta_data($html)['seekable'] ?? false) {
rewind($html);
}
$html = stream_get_contents($html);
}
$htmlPart = new TextPart($html, $this->htmlCharset, 'html');
preg_match_all('(<img\s+[^>]*src\s*=\s*(?:([\'"])cid:([^"]+)\\1|cid:([^>\s]+)))i', $html, $names);
$names = array_filter(array_unique(array_merge($names[2], $names[3])));
}
$attachmentParts = $inlineParts = [];
foreach ($this->attachments as $attachment) {
foreach ($names as $name) {
if (isset($attachment['part'])) {
continue;
}
if ($name !== $attachment['name']) {
continue;
}
if (isset($inlineParts[$name])) {
continue 2;
}
$attachment['inline'] = true;
$inlineParts[$name] = $part = $this->createDataPart($attachment);
$html = str_replace('cid:'.$name, 'cid:'.$part->getContentId(), $html);
continue 2;
}
$attachmentParts[] = $this->createDataPart($attachment);
}
if (null !== $htmlPart) {
$htmlPart = new TextPart($html, $this->htmlCharset, 'html');
}
return [$htmlPart, $attachmentParts, array_values($inlineParts)];
}
private function createDataPart(array $attachment): DataPart
{
if (isset($attachment['part'])) {
return $attachment['part'];
}
if (isset($attachment['body'])) {
$part = new DataPart($attachment['body'], $attachment['name'] ?? null, $attachment['content-type'] ?? null);
} else {
$part = DataPart::fromPath($attachment['path'] ?? '', $attachment['name'] ?? null, $attachment['content-type'] ?? null);
}
if ($attachment['inline']) {
$part->asInline();
}
return $part;
}
/**
* @return $this
*/
private function setHeaderBody(string $type, string $name, $body)
{
$this->getHeaders()->setHeaderBody($type, $name, $body);
return $this;
}
private function addListAddressHeaderBody($name, array $addresses)
{
if (!$to = $this->getHeaders()->get($name)) {
return $this->setListAddressHeaderBody($name, $addresses);
}
$to->addAddresses(Address::createArray($addresses));
return $this;
}
private function setListAddressHeaderBody($name, array $addresses)
{
$addresses = Address::createArray($addresses);
$headers = $this->getHeaders();
if ($to = $headers->get($name)) {
$to->setAddresses($addresses);
} else {
$headers->addMailboxListHeader($name, $addresses);
}
return $this;
}
/**
* @internal
*/
public function __serialize(): array
{
if (\is_resource($this->text)) {
if (stream_get_meta_data($this->text)['seekable'] ?? false) {
rewind($this->text);
}
$this->text = stream_get_contents($this->text);
}
if (\is_resource($this->html)) {
if (stream_get_meta_data($this->html)['seekable'] ?? false) {
rewind($this->html);
}
$this->html = stream_get_contents($this->html);
}
foreach ($this->attachments as $i => $attachment) {
if (isset($attachment['body']) && \is_resource($attachment['body'])) {
if (stream_get_meta_data($attachment['body'])['seekable'] ?? false) {
rewind($attachment['body']);
}
$this->attachments[$i]['body'] = stream_get_contents($attachment['body']);
}
}
return [$this->text, $this->textCharset, $this->html, $this->htmlCharset, $this->attachments, parent::__serialize()];
}
/**
* @internal
*/
public function __unserialize(array $data): void
{
[$this->text, $this->textCharset, $this->html, $this->htmlCharset, $this->attachments, $parentData] = $data;
parent::__unserialize($parentData);
}
}

30
addons/weliam_smartcity/vendor/symfony/mime/Encoder/AddressEncoderInterface.php

@ -0,0 +1,30 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime\Encoder;
use Symfony\Component\Mime\Exception\AddressEncoderException;
/**
* @author Christian Schmidt
*
* @experimental in 4.3
*/
interface AddressEncoderInterface
{
/**
* Encodes an email address.
*
* @throws AddressEncoderException if the email cannot be represented in
* the encoding implemented by this class
*/
public function encodeString(string $address): string;
}

50
addons/weliam_smartcity/vendor/symfony/mime/Encoder/Base64ContentEncoder.php

@ -0,0 +1,50 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime\Encoder;
use Symfony\Component\Mime\Exception\RuntimeException;
/**
* @author Fabien Potencier <fabien@symfony.com>
*
* @experimental in 4.3
*/
final class Base64ContentEncoder extends Base64Encoder implements ContentEncoderInterface
{
public function encodeByteStream($stream, int $maxLineLength = 0): iterable
{
if (!\is_resource($stream)) {
throw new \TypeError(sprintf('Method "%s" takes a stream as a first argument.', __METHOD__));
}
$filter = stream_filter_append($stream, 'convert.base64-encode', \STREAM_FILTER_READ, [
'line-length' => 0 >= $maxLineLength || 76 < $maxLineLength ? 76 : $maxLineLength,
'line-break-chars' => "\r\n",
]);
if (!\is_resource($filter)) {
throw new RuntimeException('Unable to set the base64 content encoder to the filter.');
}
if (stream_get_meta_data($stream)['seekable'] ?? false) {
rewind($stream);
}
while (!feof($stream)) {
yield fread($stream, 8192);
}
stream_filter_remove($filter);
}
public function getName(): string
{
return 'base64';
}
}

43
addons/weliam_smartcity/vendor/symfony/mime/Encoder/Base64Encoder.php

@ -0,0 +1,43 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime\Encoder;
/**
* @author Chris Corbyn
*
* @experimental in 4.3
*/
class Base64Encoder implements EncoderInterface
{
/**
* Takes an unencoded string and produces a Base64 encoded string from it.
*
* Base64 encoded strings have a maximum line length of 76 characters.
* If the first line needs to be shorter, indicate the difference with
* $firstLineOffset.
*/
public function encodeString(string $string, ?string $charset = 'utf-8', int $firstLineOffset = 0, int $maxLineLength = 0): string
{
if (0 >= $maxLineLength || 76 < $maxLineLength) {
$maxLineLength = 76;
}
$encodedString = base64_encode($string);
$firstLine = '';
if (0 !== $firstLineOffset) {
$firstLine = substr($encodedString, 0, $maxLineLength - $firstLineOffset)."\r\n";
$encodedString = substr($encodedString, $maxLineLength - $firstLineOffset);
}
return $firstLine.trim(chunk_split($encodedString, $maxLineLength, "\r\n"));
}
}

45
addons/weliam_smartcity/vendor/symfony/mime/Encoder/Base64MimeHeaderEncoder.php

@ -0,0 +1,45 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime\Encoder;
/**
* @author Chris Corbyn
*
* @experimental in 4.3
*/
final class Base64MimeHeaderEncoder extends Base64Encoder implements MimeHeaderEncoderInterface
{
public function getName(): string
{
return 'B';
}
/**
* Takes an unencoded string and produces a Base64 encoded string from it.
*
* If the charset is iso-2022-jp, it uses mb_encode_mimeheader instead of
* default encodeString, otherwise pass to the parent method.
*/
public function encodeString(string $string, ?string $charset = 'utf-8', int $firstLineOffset = 0, int $maxLineLength = 0): string
{
if ('iso-2022-jp' === strtolower($charset)) {
$old = mb_internal_encoding();
mb_internal_encoding('utf-8');
$newstring = mb_encode_mimeheader($string, 'iso-2022-jp', $this->getName(), "\r\n");
mb_internal_encoding($old);
return $newstring;
}
return parent::encodeString($string, $charset, $firstLineOffset, $maxLineLength);
}
}

32
addons/weliam_smartcity/vendor/symfony/mime/Encoder/ContentEncoderInterface.php

@ -0,0 +1,32 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime\Encoder;
/**
* @author Chris Corbyn
*
* @experimental in 4.3
*/
interface ContentEncoderInterface extends EncoderInterface
{
/**
* Encodes the stream to a Generator.
*
* @param resource $stream
*/
public function encodeByteStream($stream, int $maxLineLength = 0): iterable;
/**
* Gets the MIME name of this content encoding scheme.
*/
public function getName(): string;
}

37
addons/weliam_smartcity/vendor/symfony/mime/Encoder/EightBitContentEncoder.php

@ -0,0 +1,37 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime\Encoder;
/**
* @author Fabien Potencier <fabien@symfony.com>
*
* @experimental in 4.3
*/
final class EightBitContentEncoder implements ContentEncoderInterface
{
public function encodeByteStream($stream, int $maxLineLength = 0): iterable
{
while (!feof($stream)) {
yield fread($stream, 16372);
}
}
public function getName(): string
{
return '8bit';
}
public function encodeString(string $string, ?string $charset = 'utf-8', int $firstLineOffset = 0, int $maxLineLength = 0): string
{
return $string;
}
}

28
addons/weliam_smartcity/vendor/symfony/mime/Encoder/EncoderInterface.php

@ -0,0 +1,28 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime\Encoder;
/**
* @author Chris Corbyn
*
* @experimental in 4.3
*/
interface EncoderInterface
{
/**
* Encode a given string to produce an encoded string.
*
* @param int $firstLineOffset if first line needs to be shorter
* @param int $maxLineLength - 0 indicates the default length for this encoding
*/
public function encodeString(string $string, ?string $charset = 'utf-8', int $firstLineOffset = 0, int $maxLineLength = 0): string;
}

56
addons/weliam_smartcity/vendor/symfony/mime/Encoder/IdnAddressEncoder.php

@ -0,0 +1,56 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime\Encoder;
use Symfony\Component\Mime\Exception\AddressEncoderException;
/**
* An IDN email address encoder.
*
* Encodes the domain part of an address using IDN. This is compatible will all
* SMTP servers.
*
* This encoder does not support email addresses with non-ASCII characters in
* local-part (the substring before @). To send to such addresses, use
* Utf8AddressEncoder together with SmtpUtf8Handler. Your outbound SMTP server must support
* the SMTPUTF8 extension.
*
* @author Christian Schmidt
*
* @experimental in 4.3
*/
final class IdnAddressEncoder implements AddressEncoderInterface
{
/**
* Encodes the domain part of an address using IDN.
*
* @throws AddressEncoderException If local-part contains non-ASCII characters
*/
public function encodeString(string $address): string
{
$i = strrpos($address, '@');
if (false !== $i) {
$local = substr($address, 0, $i);
$domain = substr($address, $i + 1);
if (preg_match('/[^\x00-\x7F]/', $local)) {
throw new AddressEncoderException(sprintf('Non-ASCII characters not supported in local-part os "%s".', $address));
}
if (preg_match('/[^\x00-\x7F]/', $domain)) {
$address = sprintf('%s@%s', $local, idn_to_ascii($domain, 0, INTL_IDNA_VARIANT_UTS46));
}
}
return $address;
}
}

25
addons/weliam_smartcity/vendor/symfony/mime/Encoder/MimeHeaderEncoderInterface.php

@ -0,0 +1,25 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime\Encoder;
/**
* @author Chris Corbyn
*
* @experimental in 4.3
*/
interface MimeHeaderEncoderInterface
{
/**
* Get the MIME name of this content encoding scheme.
*/
public function getName(): string;
}

66
addons/weliam_smartcity/vendor/symfony/mime/Encoder/QpContentEncoder.php

@ -0,0 +1,66 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime\Encoder;
/**
* @author Lars Strojny
*
* @experimental in 4.3
*/
final class QpContentEncoder implements ContentEncoderInterface
{
public function encodeByteStream($stream, int $maxLineLength = 0): iterable
{
if (!\is_resource($stream)) {
throw new \TypeError(sprintf('Method "%s" takes a stream as a first argument.', __METHOD__));
}
// we don't use PHP stream filters here as the content should be small enough
if (stream_get_meta_data($stream)['seekable'] ?? false) {
rewind($stream);
}
yield $this->encodeString(stream_get_contents($stream), 'utf-8', 0, $maxLineLength);
}
public function getName(): string
{
return 'quoted-printable';
}
public function encodeString(string $string, ?string $charset = 'utf-8', int $firstLineOffset = 0, int $maxLineLength = 0): string
{
return $this->standardize(quoted_printable_encode($string));
}
/**
* Make sure CRLF is correct and HT/SPACE are in valid places.
*/
private function standardize(string $string): string
{
// transform CR or LF to CRLF
$string = preg_replace('~=0D(?!=0A)|(?<!=0D)=0A~', '=0D=0A', $string);
// transform =0D=0A to CRLF
$string = str_replace(["\t=0D=0A", ' =0D=0A', '=0D=0A'], ["=09\r\n", "=20\r\n", "\r\n"], $string);
switch (\ord(substr($string, -1))) {
case 0x09:
$string = substr_replace($string, '=09', -1);
break;
case 0x20:
$string = substr_replace($string, '=20', -1);
break;
}
return $string;
}
}

197
addons/weliam_smartcity/vendor/symfony/mime/Encoder/QpEncoder.php

@ -0,0 +1,197 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime\Encoder;
use Symfony\Component\Mime\CharacterStream;
/**
* @author Chris Corbyn
*
* @experimental in 4.3
*/
class QpEncoder implements EncoderInterface
{
/**
* Pre-computed QP for HUGE optimization.
*/
private static $qpMap = [
0 => '=00', 1 => '=01', 2 => '=02', 3 => '=03', 4 => '=04',
5 => '=05', 6 => '=06', 7 => '=07', 8 => '=08', 9 => '=09',
10 => '=0A', 11 => '=0B', 12 => '=0C', 13 => '=0D', 14 => '=0E',
15 => '=0F', 16 => '=10', 17 => '=11', 18 => '=12', 19 => '=13',
20 => '=14', 21 => '=15', 22 => '=16', 23 => '=17', 24 => '=18',
25 => '=19', 26 => '=1A', 27 => '=1B', 28 => '=1C', 29 => '=1D',
30 => '=1E', 31 => '=1F', 32 => '=20', 33 => '=21', 34 => '=22',
35 => '=23', 36 => '=24', 37 => '=25', 38 => '=26', 39 => '=27',
40 => '=28', 41 => '=29', 42 => '=2A', 43 => '=2B', 44 => '=2C',
45 => '=2D', 46 => '=2E', 47 => '=2F', 48 => '=30', 49 => '=31',
50 => '=32', 51 => '=33', 52 => '=34', 53 => '=35', 54 => '=36',
55 => '=37', 56 => '=38', 57 => '=39', 58 => '=3A', 59 => '=3B',
60 => '=3C', 61 => '=3D', 62 => '=3E', 63 => '=3F', 64 => '=40',
65 => '=41', 66 => '=42', 67 => '=43', 68 => '=44', 69 => '=45',
70 => '=46', 71 => '=47', 72 => '=48', 73 => '=49', 74 => '=4A',
75 => '=4B', 76 => '=4C', 77 => '=4D', 78 => '=4E', 79 => '=4F',
80 => '=50', 81 => '=51', 82 => '=52', 83 => '=53', 84 => '=54',
85 => '=55', 86 => '=56', 87 => '=57', 88 => '=58', 89 => '=59',
90 => '=5A', 91 => '=5B', 92 => '=5C', 93 => '=5D', 94 => '=5E',
95 => '=5F', 96 => '=60', 97 => '=61', 98 => '=62', 99 => '=63',
100 => '=64', 101 => '=65', 102 => '=66', 103 => '=67', 104 => '=68',
105 => '=69', 106 => '=6A', 107 => '=6B', 108 => '=6C', 109 => '=6D',
110 => '=6E', 111 => '=6F', 112 => '=70', 113 => '=71', 114 => '=72',
115 => '=73', 116 => '=74', 117 => '=75', 118 => '=76', 119 => '=77',
120 => '=78', 121 => '=79', 122 => '=7A', 123 => '=7B', 124 => '=7C',
125 => '=7D', 126 => '=7E', 127 => '=7F', 128 => '=80', 129 => '=81',
130 => '=82', 131 => '=83', 132 => '=84', 133 => '=85', 134 => '=86',
135 => '=87', 136 => '=88', 137 => '=89', 138 => '=8A', 139 => '=8B',
140 => '=8C', 141 => '=8D', 142 => '=8E', 143 => '=8F', 144 => '=90',
145 => '=91', 146 => '=92', 147 => '=93', 148 => '=94', 149 => '=95',
150 => '=96', 151 => '=97', 152 => '=98', 153 => '=99', 154 => '=9A',
155 => '=9B', 156 => '=9C', 157 => '=9D', 158 => '=9E', 159 => '=9F',
160 => '=A0', 161 => '=A1', 162 => '=A2', 163 => '=A3', 164 => '=A4',
165 => '=A5', 166 => '=A6', 167 => '=A7', 168 => '=A8', 169 => '=A9',
170 => '=AA', 171 => '=AB', 172 => '=AC', 173 => '=AD', 174 => '=AE',
175 => '=AF', 176 => '=B0', 177 => '=B1', 178 => '=B2', 179 => '=B3',
180 => '=B4', 181 => '=B5', 182 => '=B6', 183 => '=B7', 184 => '=B8',
185 => '=B9', 186 => '=BA', 187 => '=BB', 188 => '=BC', 189 => '=BD',
190 => '=BE', 191 => '=BF', 192 => '=C0', 193 => '=C1', 194 => '=C2',
195 => '=C3', 196 => '=C4', 197 => '=C5', 198 => '=C6', 199 => '=C7',
200 => '=C8', 201 => '=C9', 202 => '=CA', 203 => '=CB', 204 => '=CC',
205 => '=CD', 206 => '=CE', 207 => '=CF', 208 => '=D0', 209 => '=D1',
210 => '=D2', 211 => '=D3', 212 => '=D4', 213 => '=D5', 214 => '=D6',
215 => '=D7', 216 => '=D8', 217 => '=D9', 218 => '=DA', 219 => '=DB',
220 => '=DC', 221 => '=DD', 222 => '=DE', 223 => '=DF', 224 => '=E0',
225 => '=E1', 226 => '=E2', 227 => '=E3', 228 => '=E4', 229 => '=E5',
230 => '=E6', 231 => '=E7', 232 => '=E8', 233 => '=E9', 234 => '=EA',
235 => '=EB', 236 => '=EC', 237 => '=ED', 238 => '=EE', 239 => '=EF',
240 => '=F0', 241 => '=F1', 242 => '=F2', 243 => '=F3', 244 => '=F4',
245 => '=F5', 246 => '=F6', 247 => '=F7', 248 => '=F8', 249 => '=F9',
250 => '=FA', 251 => '=FB', 252 => '=FC', 253 => '=FD', 254 => '=FE',
255 => '=FF',
];
private static $safeMapShare = [];
/**
* A map of non-encoded ascii characters.
*
* @var string[]
*
* @internal
*/
protected $safeMap = [];
public function __construct()
{
$id = \get_class($this);
if (!isset(self::$safeMapShare[$id])) {
$this->initSafeMap();
self::$safeMapShare[$id] = $this->safeMap;
} else {
$this->safeMap = self::$safeMapShare[$id];
}
}
protected function initSafeMap(): void
{
foreach (array_merge([0x09, 0x20], range(0x21, 0x3C), range(0x3E, 0x7E)) as $byte) {
$this->safeMap[$byte] = \chr($byte);
}
}
/**
* {@inheritdoc}
*
* Takes an unencoded string and produces a QP encoded string from it.
*
* QP encoded strings have a maximum line length of 76 characters.
* If the first line needs to be shorter, indicate the difference with
* $firstLineOffset.
*/
public function encodeString(string $string, ?string $charset = 'utf-8', int $firstLineOffset = 0, int $maxLineLength = 0): string
{
if ($maxLineLength > 76 || $maxLineLength <= 0) {
$maxLineLength = 76;
}
$thisLineLength = $maxLineLength - $firstLineOffset;
$lines = [];
$lNo = 0;
$lines[$lNo] = '';
$currentLine = &$lines[$lNo++];
$size = $lineLen = 0;
$charStream = new CharacterStream($string, $charset);
// Fetching more than 4 chars at one is slower, as is fetching fewer bytes
// Conveniently 4 chars is the UTF-8 safe number since UTF-8 has up to 6
// bytes per char and (6 * 4 * 3 = 72 chars per line) * =NN is 3 bytes
while (null !== $bytes = $charStream->readBytes(4)) {
$enc = $this->encodeByteSequence($bytes, $size);
$i = strpos($enc, '=0D=0A');
$newLineLength = $lineLen + (false === $i ? $size : $i);
if ($currentLine && $newLineLength >= $thisLineLength) {
$lines[$lNo] = '';
$currentLine = &$lines[$lNo++];
$thisLineLength = $maxLineLength;
$lineLen = 0;
}
$currentLine .= $enc;
if (false === $i) {
$lineLen += $size;
} else {
// 6 is the length of '=0D=0A'.
$lineLen = $size - strrpos($enc, '=0D=0A') - 6;
}
}
return $this->standardize(implode("=\r\n", $lines));
}
/**
* Encode the given byte array into a verbatim QP form.
*/
private function encodeByteSequence(array $bytes, int &$size): string
{
$ret = '';
$size = 0;
foreach ($bytes as $b) {
if (isset($this->safeMap[$b])) {
$ret .= $this->safeMap[$b];
++$size;
} else {
$ret .= self::$qpMap[$b];
$size += 3;
}
}
return $ret;
}
/**
* Make sure CRLF is correct and HT/SPACE are in valid places.
*/
private function standardize(string $string): string
{
$string = str_replace(["\t=0D=0A", ' =0D=0A', '=0D=0A'], ["=09\r\n", "=20\r\n", "\r\n"], $string);
switch ($end = \ord(substr($string, -1))) {
case 0x09:
case 0x20:
$string = substr_replace($string, self::$qpMap[$end], -1);
}
return $string;
}
}

42
addons/weliam_smartcity/vendor/symfony/mime/Encoder/QpMimeHeaderEncoder.php

@ -0,0 +1,42 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime\Encoder;
/**
* @author Chris Corbyn
*
* @experimental in 4.3
*/
final class QpMimeHeaderEncoder extends QpEncoder implements MimeHeaderEncoderInterface
{
protected function initSafeMap(): void
{
foreach (array_merge(
range(0x61, 0x7A), range(0x41, 0x5A),
range(0x30, 0x39), [0x20, 0x21, 0x2A, 0x2B, 0x2D, 0x2F]
) as $byte) {
$this->safeMap[$byte] = \chr($byte);
}
}
public function getName(): string
{
return 'Q';
}
public function encodeString(string $string, ?string $charset = 'utf-8', int $firstLineOffset = 0, int $maxLineLength = 0): string
{
return str_replace([' ', '=20', "=\r\n"], ['_', '_', "\r\n"],
parent::encodeString($string, $charset, $firstLineOffset, $maxLineLength)
);
}
}

52
addons/weliam_smartcity/vendor/symfony/mime/Encoder/Rfc2231Encoder.php

@ -0,0 +1,52 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime\Encoder;
use Symfony\Component\Mime\CharacterStream;
/**
* @author Chris Corbyn
*
* @experimental in 4.3
*/
final class Rfc2231Encoder implements EncoderInterface
{
/**
* Takes an unencoded string and produces a string encoded according to RFC 2231 from it.
*/
public function encodeString(string $string, ?string $charset = 'utf-8', int $firstLineOffset = 0, int $maxLineLength = 0): string
{
$lines = [];
$lineCount = 0;
$lines[] = '';
$currentLine = &$lines[$lineCount++];
if (0 >= $maxLineLength) {
$maxLineLength = 75;
}
$charStream = new CharacterStream($string, $charset);
$thisLineLength = $maxLineLength - $firstLineOffset;
while (null !== $char = $charStream->read(4)) {
$encodedChar = rawurlencode($char);
if (0 !== \strlen($currentLine) && \strlen($currentLine.$encodedChar) > $thisLineLength) {
$lines[] = '';
$currentLine = &$lines[$lineCount++];
$thisLineLength = $maxLineLength;
}
$currentLine .= $encodedChar;
}
return implode("\r\n", $lines);
}
}

21
addons/weliam_smartcity/vendor/symfony/mime/Exception/AddressEncoderException.php

@ -0,0 +1,21 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime\Exception;
/**
* @author Fabien Potencier <fabien@symfony.com>
*
* @experimental in 4.3
*/
class AddressEncoderException extends RfcComplianceException
{
}

21
addons/weliam_smartcity/vendor/symfony/mime/Exception/ExceptionInterface.php

@ -0,0 +1,21 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime\Exception;
/**
* @author Fabien Potencier <fabien@symfony.com>
*
* @experimental in 4.3
*/
interface ExceptionInterface extends \Throwable
{
}

21
addons/weliam_smartcity/vendor/symfony/mime/Exception/InvalidArgumentException.php

@ -0,0 +1,21 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime\Exception;
/**
* @author Fabien Potencier <fabien@symfony.com>
*
* @experimental in 4.3
*/
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
{
}

21
addons/weliam_smartcity/vendor/symfony/mime/Exception/LogicException.php

@ -0,0 +1,21 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime\Exception;
/**
* @author Fabien Potencier <fabien@symfony.com>
*
* @experimental in 4.3
*/
class LogicException extends \LogicException implements ExceptionInterface
{
}

21
addons/weliam_smartcity/vendor/symfony/mime/Exception/RfcComplianceException.php

@ -0,0 +1,21 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime\Exception;
/**
* @author Fabien Potencier <fabien@symfony.com>
*
* @experimental in 4.3
*/
class RfcComplianceException extends \InvalidArgumentException implements ExceptionInterface
{
}

21
addons/weliam_smartcity/vendor/symfony/mime/Exception/RuntimeException.php

@ -0,0 +1,21 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime\Exception;
/**
* @author Fabien Potencier <fabien@symfony.com>
*
* @experimental in 4.3
*/
class RuntimeException extends \RuntimeException implements ExceptionInterface
{
}

95
addons/weliam_smartcity/vendor/symfony/mime/FileBinaryMimeTypeGuesser.php

@ -0,0 +1,95 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime;
use Symfony\Component\Mime\Exception\InvalidArgumentException;
use Symfony\Component\Mime\Exception\LogicException;
/**
* Guesses the MIME type with the binary "file" (only available on *nix).
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @experimental in 4.3
*/
class FileBinaryMimeTypeGuesser implements MimeTypeGuesserInterface
{
private $cmd;
/**
* The $cmd pattern must contain a "%s" string that will be replaced
* with the file name to guess.
*
* The command output must start with the MIME type of the file.
*
* @param string $cmd The command to run to get the MIME type of a file
*/
public function __construct(string $cmd = 'file -b --mime %s 2>/dev/null')
{
$this->cmd = $cmd;
}
/**
* {@inheritdoc}
*/
public function isGuesserSupported(): bool
{
static $supported = null;
if (null !== $supported) {
return $supported;
}
if ('\\' === \DIRECTORY_SEPARATOR || !\function_exists('passthru') || !\function_exists('escapeshellarg')) {
return $supported = false;
}
ob_start();
passthru('command -v file', $exitStatus);
$binPath = trim(ob_get_clean());
return $supported = 0 === $exitStatus && '' !== $binPath;
}
/**
* {@inheritdoc}
*/
public function guessMimeType(string $path): ?string
{
if (!is_file($path) || !is_readable($path)) {
throw new InvalidArgumentException(sprintf('The "%s" file does not exist or is not readable.', $path));
}
if (!$this->isGuesserSupported()) {
throw new LogicException(sprintf('The "%s" guesser is not supported.', __CLASS__));
}
ob_start();
// need to use --mime instead of -i. see #6641
passthru(sprintf($this->cmd, escapeshellarg($path)), $return);
if ($return > 0) {
ob_end_clean();
return null;
}
$type = trim(ob_get_clean());
if (!preg_match('#^([a-z0-9\-]+/[a-z0-9\-\.]+)#i', $type, $match)) {
// it's not a type, but an error message
return null;
}
return $match[1];
}
}

65
addons/weliam_smartcity/vendor/symfony/mime/FileinfoMimeTypeGuesser.php

@ -0,0 +1,65 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime;
use Symfony\Component\Mime\Exception\InvalidArgumentException;
use Symfony\Component\Mime\Exception\LogicException;
/**
* Guesses the MIME type using the PECL extension FileInfo.
*
* @author Bernhard Schussek <bschussek@gmail.com>
*
* @experimental in 4.3
*/
class FileinfoMimeTypeGuesser implements MimeTypeGuesserInterface
{
private $magicFile;
/**
* @param string $magicFile A magic file to use with the finfo instance
*
* @see http://www.php.net/manual/en/function.finfo-open.php
*/
public function __construct(string $magicFile = null)
{
$this->magicFile = $magicFile;
}
/**
* {@inheritdoc}
*/
public function isGuesserSupported(): bool
{
return \function_exists('finfo_open');
}
/**
* {@inheritdoc}
*/
public function guessMimeType(string $path): ?string
{
if (!is_file($path) || !is_readable($path)) {
throw new InvalidArgumentException(sprintf('The "%s" file does not exist or is not readable.', $path));
}
if (!$this->isGuesserSupported()) {
throw new LogicException(sprintf('The "%s" guesser is not supported.', __CLASS__));
}
if (false === $finfo = new \finfo(FILEINFO_MIME_TYPE, $this->magicFile)) {
return null;
}
return $finfo->file($path);
}
}

281
addons/weliam_smartcity/vendor/symfony/mime/Header/AbstractHeader.php

@ -0,0 +1,281 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime\Header;
use Symfony\Component\Mime\Encoder\QpMimeHeaderEncoder;
/**
* An abstract base MIME Header.
*
* @author Chris Corbyn
*
* @experimental in 4.3
*/
abstract class AbstractHeader implements HeaderInterface
{
const PHRASE_PATTERN = '(?:(?:(?:(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))*(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))|(?:(?:[ \t]*(?:\r\n))?[ \t])))?[a-zA-Z0-9!#\$%&\'\*\+\-\/=\?\^_`\{\}\|~]+(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))*(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))|(?:(?:[ \t]*(?:\r\n))?[ \t])))?)|(?:(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))*(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))|(?:(?:[ \t]*(?:\r\n))?[ \t])))?"((?:(?:[ \t]*(?:\r\n))?[ \t])?(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21\x23-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])))*(?:(?:[ \t]*(?:\r\n))?[ \t])?"(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))*(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))|(?:(?:[ \t]*(?:\r\n))?[ \t])))?))+?)';
private static $encoder;
private $name;
private $lineLength = 76;
private $lang;
private $charset = 'utf-8';
public function __construct(string $name)
{
$this->name = $name;
}
public function setCharset(string $charset)
{
$this->charset = $charset;
}
public function getCharset(): ?string
{
return $this->charset;
}
/**
* Set the language used in this Header.
*
* For example, for US English, 'en-us'.
*/
public function setLanguage(string $lang)
{
$this->lang = $lang;
}
public function getLanguage(): ?string
{
return $this->lang;
}
public function getName(): string
{
return $this->name;
}
public function setMaxLineLength(int $lineLength)
{
$this->lineLength = $lineLength;
}
public function getMaxLineLength(): int
{
return $this->lineLength;
}
public function toString(): string
{
return $this->tokensToString($this->toTokens());
}
/**
* Produces a compliant, formatted RFC 2822 'phrase' based on the string given.
*
* @param string $string as displayed
* @param bool $shorten the first line to make remove for header name
*/
protected function createPhrase(HeaderInterface $header, string $string, string $charset, bool $shorten = false): string
{
// Treat token as exactly what was given
$phraseStr = $string;
// If it's not valid
if (!preg_match('/^'.self::PHRASE_PATTERN.'$/D', $phraseStr)) {
// .. but it is just ascii text, try escaping some characters
// and make it a quoted-string
if (preg_match('/^[\x00-\x08\x0B\x0C\x0E-\x7F]*$/D', $phraseStr)) {
foreach (['\\', '"'] as $char) {
$phraseStr = str_replace($char, '\\'.$char, $phraseStr);
}
$phraseStr = '"'.$phraseStr.'"';
} else {
// ... otherwise it needs encoding
// Determine space remaining on line if first line
if ($shorten) {
$usedLength = \strlen($header->getName().': ');
} else {
$usedLength = 0;
}
$phraseStr = $this->encodeWords($header, $string, $usedLength);
}
}
return $phraseStr;
}
/**
* Encode needed word tokens within a string of input.
*/
protected function encodeWords(HeaderInterface $header, string $input, int $usedLength = -1): string
{
$value = '';
$tokens = $this->getEncodableWordTokens($input);
foreach ($tokens as $token) {
// See RFC 2822, Sect 2.2 (really 2.2 ??)
if ($this->tokenNeedsEncoding($token)) {
// Don't encode starting WSP
$firstChar = substr($token, 0, 1);
switch ($firstChar) {
case ' ':
case "\t":
$value .= $firstChar;
$token = substr($token, 1);
}
if (-1 == $usedLength) {
$usedLength = \strlen($header->getName().': ') + \strlen($value);
}
$value .= $this->getTokenAsEncodedWord($token, $usedLength);
} else {
$value .= $token;
}
}
return $value;
}
protected function tokenNeedsEncoding(string $token): bool
{
return (bool) preg_match('~[\x00-\x08\x10-\x19\x7F-\xFF\r\n]~', $token);
}
/**
* Splits a string into tokens in blocks of words which can be encoded quickly.
*
* @return string[]
*/
protected function getEncodableWordTokens(string $string): array
{
$tokens = [];
$encodedToken = '';
// Split at all whitespace boundaries
foreach (preg_split('~(?=[\t ])~', $string) as $token) {
if ($this->tokenNeedsEncoding($token)) {
$encodedToken .= $token;
} else {
if (\strlen($encodedToken) > 0) {
$tokens[] = $encodedToken;
$encodedToken = '';
}
$tokens[] = $token;
}
}
if (\strlen($encodedToken)) {
$tokens[] = $encodedToken;
}
return $tokens;
}
/**
* Get a token as an encoded word for safe insertion into headers.
*/
protected function getTokenAsEncodedWord(string $token, int $firstLineOffset = 0): string
{
if (null === self::$encoder) {
self::$encoder = new QpMimeHeaderEncoder();
}
// Adjust $firstLineOffset to account for space needed for syntax
$charsetDecl = $this->charset;
if (null !== $this->lang) {
$charsetDecl .= '*'.$this->lang;
}
$encodingWrapperLength = \strlen('=?'.$charsetDecl.'?'.self::$encoder->getName().'??=');
if ($firstLineOffset >= 75) {
//Does this logic need to be here?
$firstLineOffset = 0;
}
$encodedTextLines = explode("\r\n",
self::$encoder->encodeString($token, $this->charset, $firstLineOffset, 75 - $encodingWrapperLength)
);
if ('iso-2022-jp' !== strtolower($this->charset)) {
// special encoding for iso-2022-jp using mb_encode_mimeheader
foreach ($encodedTextLines as $lineNum => $line) {
$encodedTextLines[$lineNum] = '=?'.$charsetDecl.'?'.self::$encoder->getName().'?'.$line.'?=';
}
}
return implode("\r\n ", $encodedTextLines);
}
/**
* Generates tokens from the given string which include CRLF as individual tokens.
*
* @return string[]
*/
protected function generateTokenLines(string $token): array
{
return preg_split('~(\r\n)~', $token, -1, PREG_SPLIT_DELIM_CAPTURE);
}
/**
* Generate a list of all tokens in the final header.
*/
protected function toTokens(string $string = null): array
{
if (null === $string) {
$string = $this->getBodyAsString();
}
$tokens = [];
// Generate atoms; split at all invisible boundaries followed by WSP
foreach (preg_split('~(?=[ \t])~', $string) as $token) {
$newTokens = $this->generateTokenLines($token);
foreach ($newTokens as $newToken) {
$tokens[] = $newToken;
}
}
return $tokens;
}
/**
* Takes an array of tokens which appear in the header and turns them into
* an RFC 2822 compliant string, adding FWSP where needed.
*
* @param string[] $tokens
*/
private function tokensToString(array $tokens): string
{
$lineCount = 0;
$headerLines = [];
$headerLines[] = $this->name.': ';
$currentLine = &$headerLines[$lineCount++];
// Build all tokens back into compliant header
foreach ($tokens as $i => $token) {
// Line longer than specified maximum or token was just a new line
if (("\r\n" === $token) ||
($i > 0 && \strlen($currentLine.$token) > $this->lineLength)
&& 0 < \strlen($currentLine)) {
$headerLines[] = '';
$currentLine = &$headerLines[$lineCount++];
}
// Append token to the line
if ("\r\n" !== $token) {
$currentLine .= $token;
}
}
// Implode with FWS (RFC 2822, 2.2.3)
return implode("\r\n", $headerLines);
}
}

71
addons/weliam_smartcity/vendor/symfony/mime/Header/DateHeader.php

@ -0,0 +1,71 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime\Header;
/**
* A Date MIME Header.
*
* @author Chris Corbyn
*
* @experimental in 4.3
*/
final class DateHeader extends AbstractHeader
{
private $dateTime;
public function __construct(string $name, \DateTimeInterface $date)
{
parent::__construct($name);
$this->setDateTime($date);
}
/**
* @param \DateTimeInterface $body
*/
public function setBody($body)
{
$this->setDateTime($body);
}
/**
* @return \DateTimeImmutable
*/
public function getBody()
{
return $this->getDateTime();
}
public function getDateTime(): \DateTimeImmutable
{
return $this->dateTime;
}
/**
* Set the date-time of the Date in this Header.
*
* If a DateTime instance is provided, it is converted to DateTimeImmutable.
*/
public function setDateTime(\DateTimeInterface $dateTime)
{
if ($dateTime instanceof \DateTime) {
$immutable = new \DateTimeImmutable('@'.$dateTime->getTimestamp());
$dateTime = $immutable->setTimezone($dateTime->getTimezone());
}
$this->dateTime = $dateTime;
}
public function getBodyAsString(): string
{
return $this->dateTime->format(\DateTime::RFC2822);
}
}

67
addons/weliam_smartcity/vendor/symfony/mime/Header/HeaderInterface.php

@ -0,0 +1,67 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime\Header;
/**
* A MIME Header.
*
* @author Chris Corbyn
*
* @experimental in 4.3
*/
interface HeaderInterface
{
/**
* Sets the body.
*
* The type depends on the Header concrete class.
*
* @param mixed $body
*/
public function setBody($body);
/**
* Gets the body.
*
* The return type depends on the Header concrete class.
*
* @return mixed
*/
public function getBody();
public function setCharset(string $charset);
public function getCharset(): ?string;
public function setLanguage(string $lang);
public function getLanguage(): ?string;
public function getName(): string;
public function setMaxLineLength(int $lineLength);
public function getMaxLineLength(): int;
/**
* Gets this Header rendered as a compliant string.
*/
public function toString(): string;
/**
* Gets the header's body, prepared for folding into a final header value.
*
* This is not necessarily RFC 2822 compliant since folding white space is
* not added at this stage (see {@link toString()} for that).
*/
public function getBodyAsString(): string;
}

285
addons/weliam_smartcity/vendor/symfony/mime/Header/Headers.php

@ -0,0 +1,285 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime\Header;
use Symfony\Component\Mime\Address;
use Symfony\Component\Mime\Exception\LogicException;
use Symfony\Component\Mime\NamedAddress;
/**
* A collection of headers.
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @experimental in 4.3
*/
final class Headers
{
private static $uniqueHeaders = [
'date', 'from', 'sender', 'reply-to', 'to', 'cc', 'bcc',
'message-id', 'in-reply-to', 'references', 'subject',
];
private $headers = [];
private $lineLength = 76;
public function __construct(HeaderInterface ...$headers)
{
foreach ($headers as $header) {
$this->add($header);
}
}
public function __clone()
{
foreach ($this->headers as $name => $collection) {
foreach ($collection as $i => $header) {
$this->headers[$name][$i] = clone $header;
}
}
}
public function setMaxLineLength(int $lineLength)
{
$this->lineLength = $lineLength;
foreach ($this->all() as $header) {
$header->setMaxLineLength($lineLength);
}
}
public function getMaxLineLength(): int
{
return $this->lineLength;
}
/**
* @param (NamedAddress|Address|string)[] $addresses
*
* @return $this
*/
public function addMailboxListHeader(string $name, array $addresses)
{
return $this->add(new MailboxListHeader($name, Address::createArray($addresses)));
}
/**
* @param NamedAddress|Address|string $address
*
* @return $this
*/
public function addMailboxHeader(string $name, $address)
{
return $this->add(new MailboxHeader($name, Address::create($address)));
}
/**
* @param string|array $ids
*
* @return $this
*/
public function addIdHeader(string $name, $ids)
{
return $this->add(new IdentificationHeader($name, $ids));
}
/**
* @param Address|string $path
*
* @return $this
*/
public function addPathHeader(string $name, $path)
{
return $this->add(new PathHeader($name, $path instanceof Address ? $path : new Address($path)));
}
/**
* @return $this
*/
public function addDateHeader(string $name, \DateTimeInterface $dateTime)
{
return $this->add(new DateHeader($name, $dateTime));
}
/**
* @return $this
*/
public function addTextHeader(string $name, string $value)
{
return $this->add(new UnstructuredHeader($name, $value));
}
/**
* @return $this
*/
public function addParameterizedHeader(string $name, string $value, array $params = [])
{
return $this->add(new ParameterizedHeader($name, $value, $params));
}
public function has(string $name): bool
{
return isset($this->headers[strtolower($name)]);
}
/**
* @return $this
*/
public function add(HeaderInterface $header)
{
static $map = [
'date' => DateHeader::class,
'from' => MailboxListHeader::class,
'sender' => MailboxHeader::class,
'reply-to' => MailboxListHeader::class,
'to' => MailboxListHeader::class,
'cc' => MailboxListHeader::class,
'bcc' => MailboxListHeader::class,
'message-id' => IdentificationHeader::class,
'in-reply-to' => IdentificationHeader::class,
'references' => IdentificationHeader::class,
'return-path' => PathHeader::class,
];
$header->setMaxLineLength($this->lineLength);
$name = strtolower($header->getName());
if (isset($map[$name]) && !$header instanceof $map[$name]) {
throw new LogicException(sprintf('The "%s" header must be an instance of "%s" (got "%s").', $header->getName(), $map[$name], \get_class($header)));
}
if (\in_array($name, self::$uniqueHeaders, true) && isset($this->headers[$name]) && \count($this->headers[$name]) > 0) {
throw new LogicException(sprintf('Impossible to set header "%s" as it\'s already defined and must be unique.', $header->getName()));
}
$this->headers[$name][] = $header;
return $this;
}
public function get(string $name): ?HeaderInterface
{
$name = strtolower($name);
if (!isset($this->headers[$name])) {
return null;
}
$values = array_values($this->headers[$name]);
return array_shift($values);
}
public function all(string $name = null): iterable
{
if (null === $name) {
foreach ($this->headers as $name => $collection) {
foreach ($collection as $header) {
yield $name => $header;
}
}
} elseif (isset($this->headers[strtolower($name)])) {
foreach ($this->headers[strtolower($name)] as $header) {
yield $header;
}
}
}
public function getNames(): array
{
return array_keys($this->headers);
}
public function remove(string $name): void
{
unset($this->headers[strtolower($name)]);
}
public static function isUniqueHeader(string $name): bool
{
return \in_array($name, self::$uniqueHeaders, true);
}
public function toString(): string
{
$string = '';
foreach ($this->toArray() as $str) {
$string .= $str."\r\n";
}
return $string;
}
public function toArray(): array
{
$arr = [];
foreach ($this->all() as $header) {
if ('' !== $header->getBodyAsString()) {
$arr[] = $header->toString();
}
}
return $arr;
}
/**
* @internal
*/
public function getHeaderBody($name)
{
return $this->has($name) ? $this->get($name)->getBody() : null;
}
/**
* @internal
*/
public function setHeaderBody(string $type, string $name, $body): void
{
if ($this->has($name)) {
$this->get($name)->setBody($body);
} else {
$this->{'add'.$type.'Header'}($name, $body);
}
}
/**
* @internal
*/
public function getHeaderParameter(string $name, string $parameter): ?string
{
if (!$this->has($name)) {
return null;
}
$header = $this->get($name);
if (!$header instanceof ParameterizedHeader) {
throw new LogicException(sprintf('Unable to get parameter "%s" on header "%s" as the header is not of class "%s".', $parameter, $name, ParameterizedHeader::class));
}
return $header->getParameter($parameter);
}
/**
* @internal
*/
public function setHeaderParameter(string $name, string $parameter, $value): void
{
if (!$this->has($name)) {
throw new LogicException(sprintf('Unable to set parameter "%s" on header "%s" as the header is not defined.', $parameter, $name));
}
$header = $this->get($name);
if (!$header instanceof ParameterizedHeader) {
throw new LogicException(sprintf('Unable to set parameter "%s" on header "%s" as the header is not of class "%s".', $parameter, $name, ParameterizedHeader::class));
}
$header->setParameter($parameter, $value);
}
}

115
addons/weliam_smartcity/vendor/symfony/mime/Header/IdentificationHeader.php

@ -0,0 +1,115 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime\Header;
use Symfony\Component\Mime\Address;
use Symfony\Component\Mime\Exception\RfcComplianceException;
/**
* An ID MIME Header for something like Message-ID or Content-ID (one or more addresses).
*
* @author Chris Corbyn
*
* @experimental in 4.3
*/
final class IdentificationHeader extends AbstractHeader
{
private $ids = [];
private $idsAsAddresses = [];
/**
* @param string|array $ids
*/
public function __construct(string $name, $ids)
{
parent::__construct($name);
$this->setId($ids);
}
/**
* @param string|array $body a string ID or an array of IDs
*
* @throws RfcComplianceException
*/
public function setBody($body)
{
$this->setId($body);
}
/**
* @return array
*/
public function getBody()
{
return $this->getIds();
}
/**
* Set the ID used in the value of this header.
*
* @param string|array $id
*
* @throws RfcComplianceException
*/
public function setId($id)
{
$this->setIds(\is_array($id) ? $id : [$id]);
}
/**
* Get the ID used in the value of this Header.
*
* If multiple IDs are set only the first is returned.
*/
public function getId(): ?string
{
return $this->ids[0] ?? null;
}
/**
* Set a collection of IDs to use in the value of this Header.
*
* @param string[] $ids
*
* @throws RfcComplianceException
*/
public function setIds(array $ids)
{
$this->ids = [];
$this->idsAsAddresses = [];
foreach ($ids as $id) {
$this->idsAsAddresses[] = new Address($id);
$this->ids[] = $id;
}
}
/**
* Get the list of IDs used in this Header.
*
* @return string[]
*/
public function getIds(): array
{
return $this->ids;
}
public function getBodyAsString(): string
{
$addrs = [];
foreach ($this->idsAsAddresses as $address) {
$addrs[] = '<'.$address->toString().'>';
}
return implode(' ', $addrs);
}
}

90
addons/weliam_smartcity/vendor/symfony/mime/Header/MailboxHeader.php

@ -0,0 +1,90 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime\Header;
use Symfony\Component\Mime\Address;
use Symfony\Component\Mime\Exception\RfcComplianceException;
use Symfony\Component\Mime\NamedAddress;
/**
* A Mailbox MIME Header for something like Sender (one named address).
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @experimental in 4.3
*/
final class MailboxHeader extends AbstractHeader
{
private $address;
public function __construct(string $name, Address $address)
{
parent::__construct($name);
$this->setAddress($address);
}
/**
* @param Address $body
*
* @throws RfcComplianceException
*/
public function setBody($body)
{
$this->setAddress($body);
}
/**
* @throws RfcComplianceException
*
* @return Address
*/
public function getBody()
{
return $this->getAddress();
}
/**
* @throws RfcComplianceException
*/
public function setAddress(Address $address)
{
$this->address = $address;
}
public function getAddress(): Address
{
return $this->address;
}
public function getBodyAsString(): string
{
$str = $this->address->getEncodedAddress();
if ($this->address instanceof NamedAddress && $name = $this->address->getName()) {
$str = $this->createPhrase($this, $name, $this->getCharset(), true).' <'.$str.'>';
}
return $str;
}
/**
* Redefine the encoding requirements for an address.
*
* All "specials" must be encoded as the full header value will not be quoted
*
* @see RFC 2822 3.2.1
*/
protected function tokenNeedsEncoding(string $token): bool
{
return preg_match('/[()<>\[\]:;@\,."]/', $token) || parent::tokenNeedsEncoding($token);
}
}

139
addons/weliam_smartcity/vendor/symfony/mime/Header/MailboxListHeader.php

@ -0,0 +1,139 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime\Header;
use Symfony\Component\Mime\Address;
use Symfony\Component\Mime\Exception\RfcComplianceException;
use Symfony\Component\Mime\NamedAddress;
/**
* A Mailbox list MIME Header for something like From, To, Cc, and Bcc (one or more named addresses).
*
* @author Chris Corbyn
*
* @experimental in 4.3
*/
final class MailboxListHeader extends AbstractHeader
{
private $addresses = [];
/**
* @param (NamedAddress|Address)[] $addresses
*/
public function __construct(string $name, array $addresses)
{
parent::__construct($name);
$this->setAddresses($addresses);
}
/**
* @param (NamedAddress|Address)[] $body
*
* @throws RfcComplianceException
*/
public function setBody($body)
{
$this->setAddresses($body);
}
/**
* @throws RfcComplianceException
*
* @return (NamedAddress|Address)[]
*/
public function getBody()
{
return $this->getAddresses();
}
/**
* Sets a list of addresses to be shown in this Header.
*
* @param (NamedAddress|Address)[] $addresses
*
* @throws RfcComplianceException
*/
public function setAddresses(array $addresses)
{
$this->addresses = [];
$this->addAddresses($addresses);
}
/**
* Sets a list of addresses to be shown in this Header.
*
* @param (NamedAddress|Address)[] $addresses
*
* @throws RfcComplianceException
*/
public function addAddresses(array $addresses)
{
foreach ($addresses as $address) {
$this->addAddress($address);
}
}
/**
* @throws RfcComplianceException
*/
public function addAddress(Address $address)
{
$this->addresses[] = $address;
}
/**
* @return (NamedAddress|Address)[]
*/
public function getAddresses(): array
{
return $this->addresses;
}
/**
* Gets the full mailbox list of this Header as an array of valid RFC 2822 strings.
*
* @throws RfcComplianceException
*
* @return string[]
*/
public function getAddressStrings(): array
{
$strings = [];
foreach ($this->addresses as $address) {
$str = $address->getEncodedAddress();
if ($address instanceof NamedAddress && $name = $address->getName()) {
$str = $this->createPhrase($this, $name, $this->getCharset(), empty($strings)).' <'.$str.'>';
}
$strings[] = $str;
}
return $strings;
}
public function getBodyAsString(): string
{
return implode(', ', $this->getAddressStrings());
}
/**
* Redefine the encoding requirements for addresses.
*
* All "specials" must be encoded as the full header value will not be quoted
*
* @see RFC 2822 3.2.1
*/
protected function tokenNeedsEncoding(string $token): bool
{
return preg_match('/[()<>\[\]:;@\,."]/', $token) || parent::tokenNeedsEncoding($token);
}
}

176
addons/weliam_smartcity/vendor/symfony/mime/Header/ParameterizedHeader.php

@ -0,0 +1,176 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime\Header;
use Symfony\Component\Mime\Encoder\Rfc2231Encoder;
/**
* @author Chris Corbyn
*
* @experimental in 4.3
*/
final class ParameterizedHeader extends UnstructuredHeader
{
/**
* RFC 2231's definition of a token.
*
* @var string
*/
const TOKEN_REGEX = '(?:[\x21\x23-\x27\x2A\x2B\x2D\x2E\x30-\x39\x41-\x5A\x5E-\x7E]+)';
private $encoder;
private $parameters = [];
public function __construct(string $name, string $value, array $parameters = [])
{
parent::__construct($name, $value);
foreach ($parameters as $k => $v) {
$this->setParameter($k, $v);
}
if ('content-disposition' === strtolower($name)) {
$this->encoder = new Rfc2231Encoder();
}
}
public function setParameter(string $parameter, ?string $value)
{
$this->setParameters(array_merge($this->getParameters(), [$parameter => $value]));
}
public function getParameter(string $parameter): string
{
return $this->getParameters()[$parameter] ?? '';
}
/**
* @param string[] $parameters
*/
public function setParameters(array $parameters)
{
$this->parameters = $parameters;
}
/**
* @return string[]
*/
public function getParameters(): array
{
return $this->parameters;
}
public function getBodyAsString(): string
{
$body = parent::getBodyAsString();
foreach ($this->parameters as $name => $value) {
if (null !== $value) {
$body .= '; '.$this->createParameter($name, $value);
}
}
return $body;
}
/**
* Generate a list of all tokens in the final header.
*
* This doesn't need to be overridden in theory, but it is for implementation
* reasons to prevent potential breakage of attributes.
*/
protected function toTokens(string $string = null): array
{
$tokens = parent::toTokens(parent::getBodyAsString());
// Try creating any parameters
foreach ($this->parameters as $name => $value) {
if (null !== $value) {
// Add the semi-colon separator
$tokens[\count($tokens) - 1] .= ';';
$tokens = array_merge($tokens, $this->generateTokenLines(' '.$this->createParameter($name, $value)));
}
}
return $tokens;
}
/**
* Render a RFC 2047 compliant header parameter from the $name and $value.
*/
private function createParameter(string $name, string $value): string
{
$origValue = $value;
$encoded = false;
// Allow room for parameter name, indices, "=" and DQUOTEs
$maxValueLength = $this->getMaxLineLength() - \strlen($name.'=*N"";') - 1;
$firstLineOffset = 0;
// If it's not already a valid parameter value...
if (!preg_match('/^'.self::TOKEN_REGEX.'$/D', $value)) {
// TODO: text, or something else??
// ... and it's not ascii
if (!preg_match('/^[\x00-\x08\x0B\x0C\x0E-\x7F]*$/D', $value)) {
$encoded = true;
// Allow space for the indices, charset and language
$maxValueLength = $this->getMaxLineLength() - \strlen($name.'*N*="";') - 1;
$firstLineOffset = \strlen($this->getCharset()."'".$this->getLanguage()."'");
}
}
// Encode if we need to
if ($encoded || \strlen($value) > $maxValueLength) {
if (null !== $this->encoder) {
$value = $this->encoder->encodeString($origValue, $this->getCharset(), $firstLineOffset, $maxValueLength);
} else {
// We have to go against RFC 2183/2231 in some areas for interoperability
$value = $this->getTokenAsEncodedWord($origValue);
$encoded = false;
}
}
$valueLines = $this->encoder ? explode("\r\n", $value) : [$value];
// Need to add indices
if (\count($valueLines) > 1) {
$paramLines = [];
foreach ($valueLines as $i => $line) {
$paramLines[] = $name.'*'.$i.$this->getEndOfParameterValue($line, true, 0 === $i);
}
return implode(";\r\n ", $paramLines);
} else {
return $name.$this->getEndOfParameterValue($valueLines[0], $encoded, true);
}
}
/**
* Returns the parameter value from the "=" and beyond.
*
* @param string $value to append
*/
private function getEndOfParameterValue(string $value, bool $encoded = false, bool $firstLine = false): string
{
if (!preg_match('/^'.self::TOKEN_REGEX.'$/D', $value)) {
$value = '"'.$value.'"';
}
$prepend = '=';
if ($encoded) {
$prepend = '*=';
if ($firstLine) {
$prepend = '*='.$this->getCharset()."'".$this->getLanguage()."'";
}
}
return $prepend.$value;
}
}

67
addons/weliam_smartcity/vendor/symfony/mime/Header/PathHeader.php

@ -0,0 +1,67 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime\Header;
use Symfony\Component\Mime\Address;
use Symfony\Component\Mime\Exception\RfcComplianceException;
/**
* A Path Header, such a Return-Path (one address).
*
* @author Chris Corbyn
*
* @experimental in 4.3
*/
final class PathHeader extends AbstractHeader
{
private $address;
public function __construct(string $name, Address $address)
{
parent::__construct($name);
$this->setAddress($address);
}
/**
* @param Address $body
*
* @throws RfcComplianceException
*/
public function setBody($body)
{
$this->setAddress($body);
}
/**
* @return Address
*/
public function getBody()
{
return $this->getAddress();
}
public function setAddress(Address $address)
{
$this->address = $address;
}
public function getAddress(): Address
{
return $this->address;
}
public function getBodyAsString(): string
{
return '<'.$this->address->toString().'>';
}
}

71
addons/weliam_smartcity/vendor/symfony/mime/Header/UnstructuredHeader.php

@ -0,0 +1,71 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime\Header;
/**
* A Simple MIME Header.
*
* @author Chris Corbyn
*
* @experimental in 4.3
*/
class UnstructuredHeader extends AbstractHeader
{
private $value;
public function __construct(string $name, string $value)
{
parent::__construct($name);
$this->setValue($value);
}
/**
* @param string $body
*/
public function setBody($body)
{
$this->setValue($body);
}
/**
* @return string
*/
public function getBody()
{
return $this->getValue();
}
/**
* Get the (unencoded) value of this header.
*/
public function getValue(): string
{
return $this->value;
}
/**
* Set the (unencoded) value of this header.
*/
public function setValue(string $value)
{
$this->value = $value;
}
/**
* Get the value of this header prepared for rendering.
*/
public function getBodyAsString(): string
{
return $this->encodeWords($this, $this->value);
}
}

19
addons/weliam_smartcity/vendor/symfony/mime/LICENSE

@ -0,0 +1,19 @@
Copyright (c) 2010-2019 Fabien Potencier
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

142
addons/weliam_smartcity/vendor/symfony/mime/Message.php

@ -0,0 +1,142 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime;
use Symfony\Component\Mime\Exception\LogicException;
use Symfony\Component\Mime\Header\Headers;
use Symfony\Component\Mime\Part\AbstractPart;
use Symfony\Component\Mime\Part\TextPart;
/**
* @author Fabien Potencier <fabien@symfony.com>
*
* @experimental in 4.3
*/
class Message extends RawMessage
{
private $headers;
private $body;
public function __construct(Headers $headers = null, AbstractPart $body = null)
{
$this->headers = $headers ? clone $headers : new Headers();
$this->body = $body;
}
public function __clone()
{
if (null !== $this->headers) {
$this->headers = clone $this->headers;
}
if (null !== $this->body) {
$this->body = clone $this->body;
}
}
/**
* @return $this
*/
public function setBody(AbstractPart $body = null)
{
$this->body = $body;
return $this;
}
public function getBody(): ?AbstractPart
{
return $this->body;
}
/**
* @return $this
*/
public function setHeaders(Headers $headers)
{
$this->headers = $headers;
return $this;
}
public function getHeaders(): Headers
{
return $this->headers;
}
public function getPreparedHeaders(): Headers
{
$headers = clone $this->headers;
if (!$headers->has('From')) {
throw new LogicException('An email must have a "From" header.');
}
$headers->addTextHeader('MIME-Version', '1.0');
if (!$headers->has('Date')) {
$headers->addDateHeader('Date', new \DateTimeImmutable());
}
// determine the "real" sender
$senders = $headers->get('From')->getAddresses();
$sender = $senders[0];
if ($headers->has('Sender')) {
$sender = $headers->get('Sender')->getAddress();
} elseif (\count($senders) > 1) {
$headers->addMailboxHeader('Sender', $sender);
}
if (!$headers->has('Message-ID')) {
$headers->addIdHeader('Message-ID', $this->generateMessageId($sender->getAddress()));
}
// remove the Bcc field which should NOT be part of the sent message
$headers->remove('Bcc');
return $headers;
}
public function toString(): string
{
if (null === $body = $this->getBody()) {
$body = new TextPart('');
}
return $this->getPreparedHeaders()->toString().$body->toString();
}
public function toIterable(): iterable
{
if (null === $body = $this->getBody()) {
$body = new TextPart('');
}
yield $this->getPreparedHeaders()->toString();
yield from $body->toIterable();
}
private function generateMessageId(string $email): string
{
return bin2hex(random_bytes(16)).strstr($email, '@');
}
public function __serialize(): array
{
return [$this->headers, $this->body];
}
public function __unserialize(array $data): void
{
[$this->headers, $this->body] = $data;
}
}

127
addons/weliam_smartcity/vendor/symfony/mime/MessageConverter.php

@ -0,0 +1,127 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime;
use Symfony\Component\Mime\Exception\RuntimeException;
use Symfony\Component\Mime\Part\DataPart;
use Symfony\Component\Mime\Part\Multipart\AlternativePart;
use Symfony\Component\Mime\Part\Multipart\MixedPart;
use Symfony\Component\Mime\Part\Multipart\RelatedPart;
use Symfony\Component\Mime\Part\TextPart;
/**
* @author Fabien Potencier <fabien@symfony.com>
*
* @experimental in 4.3
*/
final class MessageConverter
{
/**
* @throws RuntimeException when unable to convert the message to an email
*/
public static function toEmail(Message $message): Email
{
if ($message instanceof Email) {
return $message;
}
// try to convert to a "simple" Email instance
$body = $message->getBody();
if ($body instanceof TextPart) {
return self::createEmailFromTextPart($message, $body);
}
if ($body instanceof AlternativePart) {
return self::createEmailFromAlternativePart($message, $body);
}
if ($body instanceof RelatedPart) {
return self::createEmailFromRelatedPart($message, $body);
}
if ($body instanceof MixedPart) {
$parts = $body->getParts();
if ($parts[0] instanceof RelatedPart) {
$email = self::createEmailFromRelatedPart($message, $parts[0]);
} elseif ($parts[0] instanceof AlternativePart) {
$email = self::createEmailFromAlternativePart($message, $parts[0]);
} elseif ($parts[0] instanceof TextPart) {
$email = self::createEmailFromTextPart($message, $parts[0]);
} else {
throw new RuntimeException(sprintf('Unable to create an Email from an instance of "%s" as the body is too complex.', \get_class($message)));
}
return self::attachParts($email, \array_slice($parts, 1));
}
throw new RuntimeException(sprintf('Unable to create an Email from an instance of "%s" as the body is too complex.', \get_class($message)));
}
private static function createEmailFromTextPart(Message $message, TextPart $part): Email
{
if ('text' === $part->getMediaType() && 'plain' === $part->getMediaSubtype()) {
return (new Email(clone $message->getHeaders()))->text($part->getBody(), $part->getPreparedHeaders()->getHeaderParameter('Content-Type', 'charset') ?: 'utf-8');
}
if ('text' === $part->getMediaType() && 'html' === $part->getMediaSubtype()) {
return (new Email(clone $message->getHeaders()))->html($part->getBody(), $part->getPreparedHeaders()->getHeaderParameter('Content-Type', 'charset') ?: 'utf-8');
}
throw new RuntimeException(sprintf('Unable to create an Email from an instance of "%s" as the body is too complex.', \get_class($message)));
}
private static function createEmailFromAlternativePart(Message $message, AlternativePart $part): Email
{
$parts = $part->getParts();
if (
2 === \count($parts) &&
$parts[0] instanceof TextPart && 'text' === $parts[0]->getMediaType() && 'plain' === $parts[0]->getMediaSubtype() &&
$parts[1] instanceof TextPart && 'text' === $parts[1]->getMediaType() && 'html' === $parts[1]->getMediaSubtype()
) {
return (new Email(clone $message->getHeaders()))
->text($parts[0]->getBody(), $parts[0]->getPreparedHeaders()->getHeaderParameter('Content-Type', 'charset') ?: 'utf-8')
->html($parts[1]->getBody(), $parts[1]->getPreparedHeaders()->getHeaderParameter('Content-Type', 'charset') ?: 'utf-8')
;
}
throw new RuntimeException(sprintf('Unable to create an Email from an instance of "%s" as the body is too complex.', \get_class($message)));
}
private static function createEmailFromRelatedPart(Message $message, RelatedPart $part): Email
{
$parts = $part->getParts();
if ($parts[0] instanceof AlternativePart) {
$email = self::createEmailFromAlternativePart($message, $parts[0]);
} elseif ($parts[0] instanceof TextPart) {
$email = self::createEmailFromTextPart($message, $parts[0]);
} else {
throw new RuntimeException(sprintf('Unable to create an Email from an instance of "%s" as the body is too complex.', \get_class($message)));
}
return self::attachParts($email, \array_slice($parts, 1));
}
private static function attachParts(Email $email, array $parts): Email
{
foreach ($parts as $part) {
if (!$part instanceof DataPart) {
throw new RuntimeException(sprintf('Unable to create an Email from an instance of "%s" as the body is too complex.', \get_class($email)));
}
$headers = $part->getPreparedHeaders();
$method = 'inline' === $headers->getHeaderBody('Content-Disposition') ? 'embed' : 'attach';
$name = $headers->getHeaderParameter('Content-Disposition', 'filename');
$email->$method($part->getBody(), $name, $part->getMediaType().'/'.$part->getMediaSubtype());
}
return $email;
}
}

39
addons/weliam_smartcity/vendor/symfony/mime/MimeTypeGuesserInterface.php

@ -0,0 +1,39 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime;
/**
* Guesses the MIME type of a file.
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @experimental in 4.3
*/
interface MimeTypeGuesserInterface
{
/**
* Returns true if this guesser is supported.
*/
public function isGuesserSupported(): bool;
/**
* Guesses the MIME type of the file with the given path.
*
* @param string $path The path to the file
*
* @return string|null The MIME type or null, if none could be guessed
*
* @throws \LogicException If the guesser is not supported
* @throws \InvalidArgumentException If the file does not exist or is not readable
*/
public function guessMimeType(string $path): ?string;
}

3154
addons/weliam_smartcity/vendor/symfony/mime/MimeTypes.php

File diff suppressed because it is too large

34
addons/weliam_smartcity/vendor/symfony/mime/MimeTypesInterface.php

@ -0,0 +1,34 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime;
/**
* @author Fabien Potencier <fabien@symfony.com>
*
* @experimental in 4.3
*/
interface MimeTypesInterface extends MimeTypeGuesserInterface
{
/**
* Gets the extensions for the given MIME type.
*
* @return string[] an array of extensions (first one is the preferred one)
*/
public function getExtensions(string $mimeType): array;
/**
* Gets the MIME types for the given extension.
*
* @return string[] an array of MIME types (first one is the preferred one)
*/
public function getMimeTypes(string $ext): array;
}

44
addons/weliam_smartcity/vendor/symfony/mime/NamedAddress.php

@ -0,0 +1,44 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime;
/**
* @author Fabien Potencier <fabien@symfony.com>
*
* @experimental in 4.3
*/
final class NamedAddress extends Address
{
private $name;
public function __construct(string $address, string $name)
{
parent::__construct($address);
$this->name = trim(str_replace(["\n", "\r"], '', $name));
}
public function getName(): string
{
return $this->name;
}
public function getEncodedNamedAddress(): string
{
return ($n = $this->getName()) ? $n.' <'.$this->getEncodedAddress().'>' : $this->getEncodedAddress();
}
public function toString(): string
{
return $this->getEncodedNamedAddress();
}
}

87
addons/weliam_smartcity/vendor/symfony/mime/Part/AbstractMultipartPart.php

@ -0,0 +1,87 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime\Part;
use Symfony\Component\Mime\Header\Headers;
/**
* @author Fabien Potencier <fabien@symfony.com>
*
* @experimental in 4.3
*/
abstract class AbstractMultipartPart extends AbstractPart
{
private $boundary;
private $parts = [];
public function __construct(AbstractPart ...$parts)
{
parent::__construct();
foreach ($parts as $part) {
$this->parts[] = $part;
}
}
/**
* @return AbstractPart[]
*/
public function getParts(): array
{
return $this->parts;
}
public function getMediaType(): string
{
return 'multipart';
}
public function getPreparedHeaders(): Headers
{
$headers = parent::getPreparedHeaders();
$headers->setHeaderParameter('Content-Type', 'boundary', $this->getBoundary());
return $headers;
}
public function bodyToString(): string
{
$parts = $this->getParts();
$string = '';
foreach ($parts as $part) {
$string .= '--'.$this->getBoundary()."\r\n".$part->toString()."\r\n";
}
$string .= '--'.$this->getBoundary()."--\r\n";
return $string;
}
public function bodyToIterable(): iterable
{
$parts = $this->getParts();
foreach ($parts as $part) {
yield '--'.$this->getBoundary()."\r\n";
yield from $part->toIterable();
yield "\r\n";
}
yield '--'.$this->getBoundary()."--\r\n";
}
private function getBoundary(): string
{
if (null === $this->boundary) {
$this->boundary = '_=_symfony_'.time().'_'.bin2hex(random_bytes(16)).'_=_';
}
return $this->boundary;
}
}

62
addons/weliam_smartcity/vendor/symfony/mime/Part/AbstractPart.php

@ -0,0 +1,62 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime\Part;
use Symfony\Component\Mime\Header\Headers;
/**
* @author Fabien Potencier <fabien@symfony.com>
*
* @experimental in 4.3
*/
abstract class AbstractPart
{
private $headers;
public function __construct()
{
$this->headers = new Headers();
}
public function getHeaders(): Headers
{
return $this->headers;
}
public function getPreparedHeaders(): Headers
{
$headers = clone $this->headers;
$headers->setHeaderBody('Parameterized', 'Content-Type', $this->getMediaType().'/'.$this->getMediaSubtype());
return $headers;
}
public function toString(): string
{
return $this->getPreparedHeaders()->toString()."\r\n".$this->bodyToString();
}
public function toIterable(): iterable
{
yield $this->getPreparedHeaders()->toString();
yield "\r\n";
yield from $this->bodyToIterable();
}
abstract public function bodyToString(): string;
abstract public function bodyToIterable(): iterable;
abstract public function getMediaType(): string;
abstract public function getMediaSubtype(): string;
}

150
addons/weliam_smartcity/vendor/symfony/mime/Part/DataPart.php

@ -0,0 +1,150 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime\Part;
use Symfony\Component\Mime\Exception\InvalidArgumentException;
use Symfony\Component\Mime\Header\Headers;
use Symfony\Component\Mime\MimeTypes;
/**
* @author Fabien Potencier <fabien@symfony.com>
*
* @experimental in 4.3
*/
class DataPart extends TextPart
{
private static $mimeTypes;
private $filename;
private $mediaType;
private $cid;
private $handle;
/**
* @param resource|string $body
*/
public function __construct($body, string $filename = null, string $contentType = null, string $encoding = null)
{
if (null === $contentType) {
$contentType = 'application/octet-stream';
}
list($this->mediaType, $subtype) = explode('/', $contentType);
parent::__construct($body, null, $subtype, $encoding);
$this->filename = $filename;
$this->setName($filename);
$this->setDisposition('attachment');
}
public static function fromPath(string $path, string $name = null, string $contentType = null): self
{
// FIXME: if file is not readable, exception?
if (null === $contentType) {
$ext = strtolower(substr($path, strrpos($path, '.') + 1));
if (null === self::$mimeTypes) {
self::$mimeTypes = new MimeTypes();
}
$contentType = self::$mimeTypes->getMimeTypes($ext)[0] ?? 'application/octet-stream';
}
if (false === $handle = @fopen($path, 'r', false)) {
throw new InvalidArgumentException(sprintf('Unable to open path "%s"', $path));
}
$p = new self($handle, $name ?: basename($path), $contentType);
$p->handle = $handle;
return $p;
}
/**
* @return $this
*/
public function asInline()
{
return $this->setDisposition('inline');
}
public function getContentId(): string
{
return $this->cid ?: $this->cid = $this->generateContentId();
}
public function hasContentId(): bool
{
return null !== $this->cid;
}
public function getMediaType(): string
{
return $this->mediaType;
}
public function getPreparedHeaders(): Headers
{
$headers = parent::getPreparedHeaders();
if (null !== $this->cid) {
$headers->setHeaderBody('Id', 'Content-ID', $this->cid);
}
if (null !== $this->filename) {
$headers->setHeaderParameter('Content-Disposition', 'filename', $this->filename);
}
return $headers;
}
private function generateContentId(): string
{
return bin2hex(random_bytes(16)).'@symfony';
}
public function __destruct()
{
if (null !== $this->handle && \is_resource($this->handle)) {
fclose($this->handle);
}
}
public function __sleep()
{
// converts the body to a string
parent::__sleep();
$this->_parent = [];
foreach (['body', 'charset', 'subtype', 'disposition', 'name', 'encoding'] as $name) {
$r = new \ReflectionProperty(TextPart::class, $name);
$r->setAccessible(true);
$this->_parent[$name] = $r->getValue($this);
}
$this->_headers = $this->getHeaders();
return ['_headers', '_parent', 'filename', 'mediaType'];
}
public function __wakeup()
{
$r = new \ReflectionProperty(AbstractPart::class, 'headers');
$r->setAccessible(true);
$r->setValue($this, $this->_headers);
unset($this->_headers);
foreach (['body', 'charset', 'subtype', 'disposition', 'name', 'encoding'] as $name) {
$r = new \ReflectionProperty(TextPart::class, $name);
$r->setAccessible(true);
$r->setValue($this, $this->_parent[$name]);
}
unset($this->_parent);
}
}

64
addons/weliam_smartcity/vendor/symfony/mime/Part/MessagePart.php

@ -0,0 +1,64 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime\Part;
use Symfony\Component\Mime\Message;
use Symfony\Component\Mime\RawMessage;
/**
* @final
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @experimental in 4.3
*/
class MessagePart extends DataPart
{
private $message;
public function __construct(RawMessage $message)
{
if ($message instanceof Message) {
$name = $message->getHeaders()->getHeaderBody('Subject').'.eml';
} else {
$name = 'email.eml';
}
parent::__construct('', $name);
$this->message = $message;
}
public function getMediaType(): string
{
return 'message';
}
public function getMediaSubtype(): string
{
return 'rfc822';
}
public function getBody(): string
{
return $this->message->toString();
}
public function bodyToString(): string
{
return $this->getBody();
}
public function bodyToIterable(): iterable
{
return $this->message->toIterable();
}
}

27
addons/weliam_smartcity/vendor/symfony/mime/Part/Multipart/AlternativePart.php

@ -0,0 +1,27 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime\Part\Multipart;
use Symfony\Component\Mime\Part\AbstractMultipartPart;
/**
* @author Fabien Potencier <fabien@symfony.com>
*
* @experimental in 4.3
*/
final class AlternativePart extends AbstractMultipartPart
{
public function getMediaSubtype(): string
{
return 'alternative';
}
}

33
addons/weliam_smartcity/vendor/symfony/mime/Part/Multipart/DigestPart.php

@ -0,0 +1,33 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime\Part\Multipart;
use Symfony\Component\Mime\Part\AbstractMultipartPart;
use Symfony\Component\Mime\Part\MessagePart;
/**
* @author Fabien Potencier <fabien@symfony.com>
*
* @experimental in 4.3
*/
final class DigestPart extends AbstractMultipartPart
{
public function __construct(MessagePart ...$parts)
{
parent::__construct(...$parts);
}
public function getMediaSubtype(): string
{
return 'digest';
}
}

96
addons/weliam_smartcity/vendor/symfony/mime/Part/Multipart/FormDataPart.php

@ -0,0 +1,96 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime\Part\Multipart;
use Symfony\Component\Mime\Exception\InvalidArgumentException;
use Symfony\Component\Mime\Part\AbstractMultipartPart;
use Symfony\Component\Mime\Part\DataPart;
use Symfony\Component\Mime\Part\TextPart;
/**
* Implements RFC 7578.
*
* @author Fabien Potencier <fabien@symfony.com>
*
* @experimental in 4.3
*/
final class FormDataPart extends AbstractMultipartPart
{
private $fields = [];
/**
* @param (string|array|DataPart)[] $fields
*/
public function __construct(array $fields = [])
{
parent::__construct();
foreach ($fields as $name => $value) {
if (!\is_string($value) && !\is_array($value) && !$value instanceof TextPart) {
throw new InvalidArgumentException(sprintf('A form field value can only be a string, an array, or an instance of TextPart ("%s" given).', \is_object($value) ? \get_class($value) : \gettype($value)));
}
$this->fields[$name] = $value;
}
// HTTP does not support \r\n in header values
$this->getHeaders()->setMaxLineLength(PHP_INT_MAX);
}
public function getMediaSubtype(): string
{
return 'form-data';
}
public function getParts(): array
{
return $this->prepareFields($this->fields);
}
private function prepareFields(array $fields): array
{
$values = [];
array_walk_recursive($fields, function ($item, $key) use (&$values) {
if (!\is_array($item)) {
$values[] = $this->preparePart($key, $item);
}
});
return $values;
}
private function preparePart($name, $value): TextPart
{
if (\is_string($value)) {
return $this->configurePart($name, new TextPart($value, 'utf-8', 'plain', '8bit'));
}
return $this->configurePart($name, $value);
}
private function configurePart(string $name, TextPart $part): TextPart
{
static $r;
if (null === $r) {
$r = new \ReflectionProperty(TextPart::class, 'encoding');
$r->setAccessible(true);
}
$part->setDisposition('form-data');
$part->setName($name);
// HTTP does not support \r\n in header values
$part->getHeaders()->setMaxLineLength(PHP_INT_MAX);
$r->setValue($part, '8bit');
return $part;
}
}

27
addons/weliam_smartcity/vendor/symfony/mime/Part/Multipart/MixedPart.php

@ -0,0 +1,27 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime\Part\Multipart;
use Symfony\Component\Mime\Part\AbstractMultipartPart;
/**
* @author Fabien Potencier <fabien@symfony.com>
*
* @experimental in 4.3
*/
final class MixedPart extends AbstractMultipartPart
{
public function getMediaSubtype(): string
{
return 'mixed';
}
}

57
addons/weliam_smartcity/vendor/symfony/mime/Part/Multipart/RelatedPart.php

@ -0,0 +1,57 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime\Part\Multipart;
use Symfony\Component\Mime\Part\AbstractMultipartPart;
use Symfony\Component\Mime\Part\AbstractPart;
/**
* @author Fabien Potencier <fabien@symfony.com>
*
* @experimental in 4.3
*/
final class RelatedPart extends AbstractMultipartPart
{
private $mainPart;
public function __construct(AbstractPart $mainPart, AbstractPart $part, AbstractPart ...$parts)
{
$this->mainPart = $mainPart;
$this->prepareParts($part, ...$parts);
parent::__construct($part, ...$parts);
}
public function getParts(): array
{
return array_merge([$this->mainPart], parent::getParts());
}
public function getMediaSubtype(): string
{
return 'related';
}
private function generateContentId(): string
{
return bin2hex(random_bytes(16)).'@symfony';
}
private function prepareParts(AbstractPart ...$parts): void
{
foreach ($parts as $part) {
if (!$part->getHeaders()->has('Content-ID')) {
$part->getHeaders()->setHeaderBody('Id', 'Content-ID', $this->generateContentId());
}
}
}
}

190
addons/weliam_smartcity/vendor/symfony/mime/Part/TextPart.php

@ -0,0 +1,190 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime\Part;
use Symfony\Component\Mime\Encoder\Base64ContentEncoder;
use Symfony\Component\Mime\Encoder\ContentEncoderInterface;
use Symfony\Component\Mime\Encoder\EightBitContentEncoder;
use Symfony\Component\Mime\Encoder\QpContentEncoder;
use Symfony\Component\Mime\Exception\InvalidArgumentException;
use Symfony\Component\Mime\Header\Headers;
/**
* @author Fabien Potencier <fabien@symfony.com>
*
* @experimental in 4.3
*/
class TextPart extends AbstractPart
{
private static $encoders = [];
private $body;
private $charset;
private $subtype;
private $disposition;
private $name;
private $encoding;
/**
* @param resource|string $body
*/
public function __construct($body, ?string $charset = 'utf-8', $subtype = 'plain', string $encoding = null)
{
parent::__construct();
if (!\is_string($body) && !\is_resource($body)) {
throw new \TypeError(sprintf('The body of "%s" must be a string or a resource (got "%s").', self::class, \is_object($body) ? \get_class($body) : \gettype($body)));
}
$this->body = $body;
$this->charset = $charset;
$this->subtype = $subtype;
if (null === $encoding) {
$this->encoding = $this->chooseEncoding();
} else {
if ('quoted-printable' !== $encoding && 'base64' !== $encoding && '8bit' !== $encoding) {
throw new InvalidArgumentException(sprintf('The encoding must be one of "quoted-printable", "base64", or "8bit" ("%s" given).', $encoding));
}
$this->encoding = $encoding;
}
}
public function getMediaType(): string
{
return 'text';
}
public function getMediaSubtype(): string
{
return $this->subtype;
}
/**
* @param string $disposition one of attachment, inline, or form-data
*
* @return $this
*/
public function setDisposition(string $disposition)
{
$this->disposition = $disposition;
return $this;
}
/**
* Sets the name of the file (used by FormDataPart).
*
* @return $this
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
public function getBody(): string
{
if (!\is_resource($this->body)) {
return $this->body;
}
if (stream_get_meta_data($this->body)['seekable'] ?? false) {
rewind($this->body);
}
return stream_get_contents($this->body) ?: '';
}
public function bodyToString(): string
{
return $this->getEncoder()->encodeString($this->getBody(), $this->charset);
}
public function bodyToIterable(): iterable
{
if (\is_resource($this->body)) {
if (stream_get_meta_data($this->body)['seekable'] ?? false) {
rewind($this->body);
}
yield from $this->getEncoder()->encodeByteStream($this->body);
} else {
yield $this->getEncoder()->encodeString($this->body);
}
}
public function getPreparedHeaders(): Headers
{
$headers = parent::getPreparedHeaders();
$headers->setHeaderBody('Parameterized', 'Content-Type', $this->getMediaType().'/'.$this->getMediaSubtype());
if ($this->charset) {
$headers->setHeaderParameter('Content-Type', 'charset', $this->charset);
}
if ($this->name) {
$headers->setHeaderParameter('Content-Type', 'name', $this->name);
}
$headers->setHeaderBody('Text', 'Content-Transfer-Encoding', $this->encoding);
if (!$headers->has('Content-Disposition') && null !== $this->disposition) {
$headers->setHeaderBody('Parameterized', 'Content-Disposition', $this->disposition);
if ($this->name) {
$headers->setHeaderParameter('Content-Disposition', 'name', $this->name);
}
}
return $headers;
}
private function getEncoder(): ContentEncoderInterface
{
if ('8bit' === $this->encoding) {
return self::$encoders[$this->encoding] ?? (self::$encoders[$this->encoding] = new EightBitContentEncoder());
}
if ('quoted-printable' === $this->encoding) {
return self::$encoders[$this->encoding] ?? (self::$encoders[$this->encoding] = new QpContentEncoder());
}
return self::$encoders[$this->encoding] ?? (self::$encoders[$this->encoding] = new Base64ContentEncoder());
}
private function chooseEncoding(): string
{
if (null === $this->charset) {
return 'base64';
}
return 'quoted-printable';
}
public function __sleep()
{
// convert resources to strings for serialization
if (\is_resource($this->body)) {
$this->body = $this->getBody();
}
$this->_headers = $this->getHeaders();
return ['_headers', 'body', 'charset', 'subtype', 'disposition', 'name', 'encoding'];
}
public function __wakeup()
{
$r = new \ReflectionProperty(AbstractPart::class, 'headers');
$r->setAccessible(true);
$r->setValue($this, $this->_headers);
unset($this->_headers);
}
}

18
addons/weliam_smartcity/vendor/symfony/mime/README.md

@ -0,0 +1,18 @@
MIME Component
==============
The MIME component allows manipulating MIME messages.
**This Component is experimental**.
[Experimental features](https://symfony.com/doc/current/contributing/code/experimental.html)
are not covered by Symfony's
[Backward Compatibility Promise](https://symfony.com/doc/current/contributing/code/bc.html).
Resources
---------
* [Documentation](https://symfony.com/doc/current/components/mime.html)
* [Contributing](https://symfony.com/doc/current/contributing/index.html)
* [Report issues](https://github.com/symfony/symfony/issues) and
[send Pull Requests](https://github.com/symfony/symfony/pulls)
in the [main Symfony repository](https://github.com/symfony/symfony)

81
addons/weliam_smartcity/vendor/symfony/mime/RawMessage.php

@ -0,0 +1,81 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime;
/**
* @author Fabien Potencier <fabien@symfony.com>
*
* @experimental in 4.3
*/
class RawMessage implements \Serializable
{
private $message;
/**
* @param iterable|string $message
*/
public function __construct($message)
{
$this->message = $message;
}
public function toString(): string
{
if (\is_string($this->message)) {
return $this->message;
}
return $this->message = implode('', iterator_to_array($this->message, false));
}
public function toIterable(): iterable
{
if (\is_string($this->message)) {
yield $this->message;
return;
}
$message = '';
foreach ($this->message as $chunk) {
$message .= $chunk;
yield $chunk;
}
$this->message = $message;
}
/**
* @internal
*/
final public function serialize()
{
return serialize($this->__serialize());
}
/**
* @internal
*/
final public function unserialize($serialized)
{
$this->__unserialize(unserialize($serialized));
}
public function __serialize(): array
{
return [$this->message];
}
public function __unserialize(array $data): void
{
[$this->message] = $data;
}
}

166
addons/weliam_smartcity/vendor/symfony/mime/Resources/bin/update_mime_types.php

@ -0,0 +1,166 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
// load new map
$data = file_get_contents('https://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types');
$new = [];
foreach (explode("\n", $data) as $line) {
if (!$line || '#' == $line[0]) {
continue;
}
$mimeType = substr($line, 0, strpos($line, "\t"));
$extensions = explode(' ', substr($line, strrpos($line, "\t") + 1));
$new[$mimeType] = $extensions;
}
$xml = simplexml_load_string(file_get_contents('https://raw.github.com/minad/mimemagic/master/script/freedesktop.org.xml'));
foreach ($xml as $node) {
$exts = [];
foreach ($node->glob as $glob) {
$pattern = (string) $glob['pattern'];
if ('*' != $pattern[0] || '.' != $pattern[1]) {
continue;
}
$exts[] = substr($pattern, 2);
}
if (!$exts) {
continue;
}
$mt = strtolower((string) $node['type']);
$new[$mt] = array_merge($new[$mt] ?? [], $exts);
foreach ($node->alias as $alias) {
$mt = strtolower((string) $alias['type']);
$new[$mt] = array_merge($new[$mt] ?? [], $exts);
}
}
// load current map
$data = file_get_contents($output = __DIR__.'/../../MimeTypes.php');
$current = [];
$pre = '';
$post = '';
foreach (explode("\n", $data) as $line) {
if (!preg_match("{^ '([^']+/[^']+)' => \['(.+)'\],$}", $line, $matches)) {
if (!$current) {
$pre .= $line."\n";
} else {
$post .= $line."\n";
}
continue;
}
$current[$matches[1]] = explode("', '", $matches[2]);
}
// we merge the 2 maps (we never remove old mime types)
$map = array_replace_recursive($current, $new);
ksort($map);
$data = $pre;
foreach ($map as $mimeType => $exts) {
$data .= sprintf(" '%s' => ['%s'],\n", $mimeType, implode("', '", array_unique($exts)));
}
$data .= $post;
// reverse map
// we prefill the extensions with some preferences for content-types
$exts = [
'aif' => ['audio/x-aiff'],
'aiff' => ['audio/x-aiff'],
'aps' => ['application/postscript'],
'avi' => ['video/avi'],
'bmp' => ['image/bmp'],
'bz2' => ['application/x-bz2'],
'css' => ['text/css'],
'csv' => ['text/csv'],
'dmg' => ['application/x-apple-diskimage'],
'doc' => ['application/msword'],
'docx' => ['application/vnd.openxmlformats-officedocument.wordprocessingml.document'],
'eml' => ['message/rfc822'],
'exe' => ['application/x-ms-dos-executable'],
'flv' => ['video/x-flv'],
'gif' => ['image/gif'],
'gz' => ['application/x-gzip'],
'hqx' => ['application/stuffit'],
'htm' => ['text/html'],
'html' => ['text/html'],
'jar' => ['application/x-java-archive'],
'jpeg' => ['image/jpeg'],
'jpg' => ['image/jpeg'],
'js' => ['text/javascript'],
'm3u' => ['audio/x-mpegurl'],
'm4a' => ['audio/mp4'],
'mdb' => ['application/x-msaccess'],
'mid' => ['audio/midi'],
'midi' => ['audio/midi'],
'mov' => ['video/quicktime'],
'mp3' => ['audio/mpeg'],
'mp4' => ['video/mp4'],
'mpeg' => ['video/mpeg'],
'mpg' => ['video/mpeg'],
'ogg' => ['audio/ogg'],
'pdf' => ['application/pdf'],
'php' => ['application/x-php'],
'php3' => ['application/x-php'],
'php4' => ['application/x-php'],
'php5' => ['application/x-php'],
'png' => ['image/png'],
'ppt' => ['application/vnd.ms-powerpoint'],
'pptx' => ['application/vnd.openxmlformats-officedocument.presentationml.presentation'],
'ps' => ['application/postscript'],
'rar' => ['application/x-rar-compressed'],
'rtf' => ['application/rtf'],
'sit' => ['application/x-stuffit'],
'svg' => ['image/svg+xml'],
'tar' => ['application/x-tar'],
'tif' => ['image/tiff'],
'tiff' => ['image/tiff'],
'ttf' => ['application/x-font-truetype'],
'txt' => ['text/plain'],
'vcf' => ['text/x-vcard'],
'wav' => ['audio/wav'],
'wma' => ['audio/x-ms-wma'],
'wmv' => ['audio/x-ms-wmv'],
'xls' => ['application/vnd.ms-excel'],
'xlsx' => ['application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'],
'xml' => ['application/xml'],
'zip' => ['application/zip'],
];
foreach ($map as $mimeType => $extensions) {
foreach ($extensions as $extension) {
$exts[$extension][] = $mimeType;
}
}
ksort($exts);
$updated = '';
$state = 0;
foreach (explode("\n", $data) as $line) {
if (!preg_match("{^ '([^'/]+)' => \['(.+)'\],$}", $line, $matches)) {
if (1 === $state) {
$state = 2;
foreach ($exts as $ext => $mimeTypes) {
$updated .= sprintf(" '%s' => ['%s'],\n", $ext, implode("', '", array_unique($mimeTypes)));
}
}
$updated .= $line."\n";
continue;
}
$state = 1;
}
$updated = preg_replace('{Updated from upstream on .+?\.}', 'Updated from upstream on '.date('Y-m-d'), $updated, -1);
file_put_contents($output, rtrim($updated, "\n")."\n");
echo "Done.\n";

102
addons/weliam_smartcity/vendor/symfony/mime/Tests/AbstractMimeTypeGuesserTest.php

@ -0,0 +1,102 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime\Tests;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Mime\MimeTypeGuesserInterface;
abstract class AbstractMimeTypeGuesserTest extends TestCase
{
public static function tearDownAfterClass(): void
{
$path = __DIR__.'/Fixtures/mimetypes/to_delete';
if (file_exists($path)) {
@chmod($path, 0666);
@unlink($path);
}
}
abstract protected function getGuesser(): MimeTypeGuesserInterface;
public function testGuessImageWithoutExtension()
{
if (!$this->getGuesser()->isGuesserSupported()) {
$this->markTestSkipped('Guesser is not supported');
}
$this->assertEquals('image/gif', $this->getGuesser()->guessMimeType(__DIR__.'/Fixtures/mimetypes/test'));
}
public function testGuessImageWithDirectory()
{
if (!$this->getGuesser()->isGuesserSupported()) {
$this->markTestSkipped('Guesser is not supported');
}
$this->expectException('\InvalidArgumentException');
$this->getGuesser()->guessMimeType(__DIR__.'/Fixtures/mimetypes/directory');
}
public function testGuessImageWithKnownExtension()
{
if (!$this->getGuesser()->isGuesserSupported()) {
$this->markTestSkipped('Guesser is not supported');
}
$this->assertEquals('image/gif', $this->getGuesser()->guessMimeType(__DIR__.'/Fixtures/mimetypes/test.gif'));
}
public function testGuessFileWithUnknownExtension()
{
if (!$this->getGuesser()->isGuesserSupported()) {
$this->markTestSkipped('Guesser is not supported');
}
$this->assertEquals('application/octet-stream', $this->getGuesser()->guessMimeType(__DIR__.'/Fixtures/mimetypes/.unknownextension'));
}
public function testGuessWithIncorrectPath()
{
if (!$this->getGuesser()->isGuesserSupported()) {
$this->markTestSkipped('Guesser is not supported');
}
$this->expectException('\InvalidArgumentException');
$this->getGuesser()->guessMimeType(__DIR__.'/Fixtures/mimetypes/not_here');
}
public function testGuessWithNonReadablePath()
{
if (!$this->getGuesser()->isGuesserSupported()) {
$this->markTestSkipped('Guesser is not supported');
}
if ('\\' === \DIRECTORY_SEPARATOR) {
$this->markTestSkipped('Can not verify chmod operations on Windows');
}
if (!getenv('USER') || 'root' === getenv('USER')) {
$this->markTestSkipped('This test will fail if run under superuser');
}
$path = __DIR__.'/Fixtures/mimetypes/to_delete';
touch($path);
@chmod($path, 0333);
if ('0333' == substr(sprintf('%o', fileperms($path)), -4)) {
$this->expectException('\InvalidArgumentException');
$this->getGuesser()->guessMimeType($path);
} else {
$this->markTestSkipped('Can not verify chmod operations, change of file permissions failed');
}
}
}

61
addons/weliam_smartcity/vendor/symfony/mime/Tests/AddressTest.php

@ -0,0 +1,61 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime\Tests;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Mime\Address;
use Symfony\Component\Mime\NamedAddress;
class AddressTest extends TestCase
{
public function testConstructor()
{
$a = new Address('fabien@symfonï.com');
$this->assertEquals('fabien@symfonï.com', $a->getAddress());
$this->assertEquals('fabien@xn--symfon-nwa.com', $a->toString());
$this->assertEquals('fabien@xn--symfon-nwa.com', $a->getEncodedAddress());
}
public function testConstructorWithInvalidAddress()
{
$this->expectException(\InvalidArgumentException::class);
new Address('fab pot@symfony.com');
}
public function testCreate()
{
$this->assertSame($a = new Address('fabien@symfony.com'), Address::create($a));
$this->assertSame($b = new NamedAddress('helene@symfony.com', 'Helene'), Address::create($b));
$this->assertEquals($a, Address::create('fabien@symfony.com'));
}
public function testCreateWrongArg()
{
$this->expectException(\InvalidArgumentException::class);
Address::create(new \stdClass());
}
public function testCreateArray()
{
$fabien = new Address('fabien@symfony.com');
$helene = new NamedAddress('helene@symfony.com', 'Helene');
$this->assertSame([$fabien, $helene], Address::createArray([$fabien, $helene]));
$this->assertEquals([$fabien], Address::createArray(['fabien@symfony.com']));
}
public function testCreateArrayWrongArg()
{
$this->expectException(\InvalidArgumentException::class);
Address::createArray([new \stdClass()]);
}
}

87
addons/weliam_smartcity/vendor/symfony/mime/Tests/CharacterStreamTest.php

@ -0,0 +1,87 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime\Tests;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Mime\CharacterStream;
class CharacterStreamTest extends TestCase
{
public function testReadCharactersAreInTact()
{
$stream = new CharacterStream(pack('C*', 0xD0, 0x94, 0xD0, 0xB6, 0xD0, 0xBE));
$stream->write(pack('C*',
0xD0, 0xBB,
0xD1, 0x8E,
0xD0, 0xB1,
0xD1, 0x8B,
0xD1, 0x85
));
$this->assertSame(pack('C*', 0xD0, 0x94), $stream->read(1));
$this->assertSame(pack('C*', 0xD0, 0xB6, 0xD0, 0xBE), $stream->read(2));
$this->assertSame(pack('C*', 0xD0, 0xBB), $stream->read(1));
$this->assertSame(pack('C*', 0xD1, 0x8E, 0xD0, 0xB1, 0xD1, 0x8B), $stream->read(3));
$this->assertSame(pack('C*', 0xD1, 0x85), $stream->read(1));
$this->assertNull($stream->read(1));
}
public function testCharactersCanBeReadAsByteArrays()
{
$stream = new CharacterStream(pack('C*', 0xD0, 0x94, 0xD0, 0xB6, 0xD0, 0xBE));
$stream->write(pack('C*',
0xD0, 0xBB,
0xD1, 0x8E,
0xD0, 0xB1,
0xD1, 0x8B,
0xD1, 0x85
));
$this->assertEquals([0xD0, 0x94], $stream->readBytes(1));
$this->assertEquals([0xD0, 0xB6, 0xD0, 0xBE], $stream->readBytes(2));
$this->assertEquals([0xD0, 0xBB], $stream->readBytes(1));
$this->assertEquals([0xD1, 0x8E, 0xD0, 0xB1, 0xD1, 0x8B], $stream->readBytes(3));
$this->assertEquals([0xD1, 0x85], $stream->readBytes(1));
$this->assertNull($stream->readBytes(1));
}
public function testRequestingLargeCharCountPastEndOfStream()
{
$stream = new CharacterStream(pack('C*', 0xD0, 0x94, 0xD0, 0xB6, 0xD0, 0xBE));
$this->assertSame(pack('C*', 0xD0, 0x94, 0xD0, 0xB6, 0xD0, 0xBE), $stream->read(100));
$this->assertNull($stream->read(1));
}
public function testRequestingByteArrayCountPastEndOfStream()
{
$stream = new CharacterStream(pack('C*', 0xD0, 0x94, 0xD0, 0xB6, 0xD0, 0xBE));
$this->assertEquals([0xD0, 0x94, 0xD0, 0xB6, 0xD0, 0xBE], $stream->readBytes(100));
$this->assertNull($stream->readBytes(1));
}
public function testPointerOffsetCanBeSet()
{
$stream = new CharacterStream(pack('C*', 0xD0, 0x94, 0xD0, 0xB6, 0xD0, 0xBE));
$this->assertSame(pack('C*', 0xD0, 0x94), $stream->read(1));
$stream->setPointer(0);
$this->assertSame(pack('C*', 0xD0, 0x94), $stream->read(1));
$stream->setPointer(2);
$this->assertSame(pack('C*', 0xD0, 0xBE), $stream->read(1));
}
public function testAlgorithmWithFixedWidthCharsets()
{
$stream = new CharacterStream(pack('C*', 0xD1, 0x8D, 0xD0, 0xBB, 0xD0, 0xB0));
$this->assertSame(pack('C*', 0xD1, 0x8D), $stream->read(1));
$this->assertSame(pack('C*', 0xD0, 0xBB), $stream->read(1));
$this->assertSame(pack('C*', 0xD0, 0xB0), $stream->read(1));
$this->assertNull($stream->read(1));
}
}

42
addons/weliam_smartcity/vendor/symfony/mime/Tests/DependencyInjection/AddMimeTypeGuesserPassTest.php

@ -0,0 +1,42 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime\Tests\DependencyInjection;
use PHPUnit\Framework\TestCase;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\Mime\DependencyInjection\AddMimeTypeGuesserPass;
use Symfony\Component\Mime\FileinfoMimeTypeGuesser;
use Symfony\Component\Mime\MimeTypes;
class AddMimeTypeGuesserPassTest extends TestCase
{
public function testTags()
{
$container = new ContainerBuilder();
$container->addCompilerPass(new AddMimeTypeGuesserPass());
$definition = new Definition(FileinfoMimeTypeGuesser::class);
$definition->addArgument('/path/to/magic/file');
$definition->addTag('mime.mime_type_guesser');
$container->setDefinition('some_mime_type_guesser', $definition->setPublic(true));
$container->register('mime_types', MimeTypes::class)->setPublic(true);
$container->compile();
$router = $container->getDefinition('mime_types');
$calls = $router->getMethodCalls();
$this->assertCount(1, $calls);
$this->assertEquals('registerGuesser', $calls[0][0]);
$this->assertEquals(new Reference('some_mime_type_guesser'), $calls[0][1][0]);
}
}

389
addons/weliam_smartcity/vendor/symfony/mime/Tests/EmailTest.php

@ -0,0 +1,389 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime\Tests;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Mime\Address;
use Symfony\Component\Mime\Email;
use Symfony\Component\Mime\NamedAddress;
use Symfony\Component\Mime\Part\DataPart;
use Symfony\Component\Mime\Part\Multipart\AlternativePart;
use Symfony\Component\Mime\Part\Multipart\MixedPart;
use Symfony\Component\Mime\Part\Multipart\RelatedPart;
use Symfony\Component\Mime\Part\TextPart;
class EmailTest extends TestCase
{
public function testSubject()
{
$e = new Email();
$e->subject('Subject');
$this->assertEquals('Subject', $e->getSubject());
}
public function testDate()
{
$e = new Email();
$e->date($d = new \DateTimeImmutable());
$this->assertSame($d, $e->getDate());
}
public function testReturnPath()
{
$e = new Email();
$e->returnPath('fabien@symfony.com');
$this->assertEquals(new Address('fabien@symfony.com'), $e->getReturnPath());
}
public function testSender()
{
$e = new Email();
$e->sender('fabien@symfony.com');
$this->assertEquals(new Address('fabien@symfony.com'), $e->getSender());
$e->sender($fabien = new Address('fabien@symfony.com'));
$this->assertSame($fabien, $e->getSender());
}
public function testFrom()
{
$e = new Email();
$helene = new Address('helene@symfony.com');
$thomas = new NamedAddress('thomas@symfony.com', 'Thomas');
$caramel = new Address('caramel@symfony.com');
$this->assertSame($e, $e->from('fabien@symfony.com', $helene, $thomas));
$v = $e->getFrom();
$this->assertCount(3, $v);
$this->assertEquals(new Address('fabien@symfony.com'), $v[0]);
$this->assertSame($helene, $v[1]);
$this->assertSame($thomas, $v[2]);
$this->assertSame($e, $e->addFrom('lucas@symfony.com', $caramel));
$v = $e->getFrom();
$this->assertCount(5, $v);
$this->assertEquals(new Address('fabien@symfony.com'), $v[0]);
$this->assertSame($helene, $v[1]);
$this->assertSame($thomas, $v[2]);
$this->assertEquals(new Address('lucas@symfony.com'), $v[3]);
$this->assertSame($caramel, $v[4]);
$e = new Email();
$e->addFrom('lucas@symfony.com', $caramel);
$this->assertCount(2, $e->getFrom());
$e = new Email();
$e->from('lucas@symfony.com');
$e->from($caramel);
$this->assertSame([$caramel], $e->getFrom());
}
public function testReplyTo()
{
$e = new Email();
$helene = new Address('helene@symfony.com');
$thomas = new NamedAddress('thomas@symfony.com', 'Thomas');
$caramel = new Address('caramel@symfony.com');
$this->assertSame($e, $e->replyTo('fabien@symfony.com', $helene, $thomas));
$v = $e->getReplyTo();
$this->assertCount(3, $v);
$this->assertEquals(new Address('fabien@symfony.com'), $v[0]);
$this->assertSame($helene, $v[1]);
$this->assertSame($thomas, $v[2]);
$this->assertSame($e, $e->addReplyTo('lucas@symfony.com', $caramel));
$v = $e->getReplyTo();
$this->assertCount(5, $v);
$this->assertEquals(new Address('fabien@symfony.com'), $v[0]);
$this->assertSame($helene, $v[1]);
$this->assertSame($thomas, $v[2]);
$this->assertEquals(new Address('lucas@symfony.com'), $v[3]);
$this->assertSame($caramel, $v[4]);
$e = new Email();
$e->addReplyTo('lucas@symfony.com', $caramel);
$this->assertCount(2, $e->getReplyTo());
$e = new Email();
$e->replyTo('lucas@symfony.com');
$e->replyTo($caramel);
$this->assertSame([$caramel], $e->getReplyTo());
}
public function testTo()
{
$e = new Email();
$helene = new Address('helene@symfony.com');
$thomas = new NamedAddress('thomas@symfony.com', 'Thomas');
$caramel = new Address('caramel@symfony.com');
$this->assertSame($e, $e->to('fabien@symfony.com', $helene, $thomas));
$v = $e->getTo();
$this->assertCount(3, $v);
$this->assertEquals(new Address('fabien@symfony.com'), $v[0]);
$this->assertSame($helene, $v[1]);
$this->assertSame($thomas, $v[2]);
$this->assertSame($e, $e->addTo('lucas@symfony.com', $caramel));
$v = $e->getTo();
$this->assertCount(5, $v);
$this->assertEquals(new Address('fabien@symfony.com'), $v[0]);
$this->assertSame($helene, $v[1]);
$this->assertSame($thomas, $v[2]);
$this->assertEquals(new Address('lucas@symfony.com'), $v[3]);
$this->assertSame($caramel, $v[4]);
$e = new Email();
$e->addTo('lucas@symfony.com', $caramel);
$this->assertCount(2, $e->getTo());
$e = new Email();
$e->to('lucas@symfony.com');
$e->to($caramel);
$this->assertSame([$caramel], $e->getTo());
}
public function testCc()
{
$e = new Email();
$helene = new Address('helene@symfony.com');
$thomas = new NamedAddress('thomas@symfony.com', 'Thomas');
$caramel = new Address('caramel@symfony.com');
$this->assertSame($e, $e->cc('fabien@symfony.com', $helene, $thomas));
$v = $e->getCc();
$this->assertCount(3, $v);
$this->assertEquals(new Address('fabien@symfony.com'), $v[0]);
$this->assertSame($helene, $v[1]);
$this->assertSame($thomas, $v[2]);
$this->assertSame($e, $e->addCc('lucas@symfony.com', $caramel));
$v = $e->getCc();
$this->assertCount(5, $v);
$this->assertEquals(new Address('fabien@symfony.com'), $v[0]);
$this->assertSame($helene, $v[1]);
$this->assertSame($thomas, $v[2]);
$this->assertEquals(new Address('lucas@symfony.com'), $v[3]);
$this->assertSame($caramel, $v[4]);
$e = new Email();
$e->addCc('lucas@symfony.com', $caramel);
$this->assertCount(2, $e->getCc());
$e = new Email();
$e->cc('lucas@symfony.com');
$e->cc($caramel);
$this->assertSame([$caramel], $e->getCc());
}
public function testBcc()
{
$e = new Email();
$helene = new Address('helene@symfony.com');
$thomas = new NamedAddress('thomas@symfony.com', 'Thomas');
$caramel = new Address('caramel@symfony.com');
$this->assertSame($e, $e->bcc('fabien@symfony.com', $helene, $thomas));
$v = $e->getBcc();
$this->assertCount(3, $v);
$this->assertEquals(new Address('fabien@symfony.com'), $v[0]);
$this->assertSame($helene, $v[1]);
$this->assertSame($thomas, $v[2]);
$this->assertSame($e, $e->addBcc('lucas@symfony.com', $caramel));
$v = $e->getBcc();
$this->assertCount(5, $v);
$this->assertEquals(new Address('fabien@symfony.com'), $v[0]);
$this->assertSame($helene, $v[1]);
$this->assertSame($thomas, $v[2]);
$this->assertEquals(new Address('lucas@symfony.com'), $v[3]);
$this->assertSame($caramel, $v[4]);
$e = new Email();
$e->addBcc('lucas@symfony.com', $caramel);
$this->assertCount(2, $e->getBcc());
$e = new Email();
$e->bcc('lucas@symfony.com');
$e->bcc($caramel);
$this->assertSame([$caramel], $e->getBcc());
}
public function testPriority()
{
$e = new Email();
$this->assertEquals(3, $e->getPriority());
$e->priority(1);
$this->assertEquals(1, $e->getPriority());
$e->priority(10);
$this->assertEquals(5, $e->getPriority());
$e->priority(-10);
$this->assertEquals(1, $e->getPriority());
}
public function testGenerateBodyThrowsWhenEmptyBody()
{
$this->expectException(\LogicException::class);
(new Email())->getBody();
}
public function testGetBody()
{
$e = new Email();
$e->setBody($text = new TextPart('text content'));
$this->assertEquals($text, $e->getBody());
}
public function testGenerateBody()
{
$text = new TextPart('text content');
$html = new TextPart('html content', 'utf-8', 'html');
$att = new DataPart($file = fopen(__DIR__.'/Fixtures/mimetypes/test', 'r'));
$img = new DataPart($image = fopen(__DIR__.'/Fixtures/mimetypes/test.gif', 'r'), 'test.gif');
$e = new Email();
$e->text('text content');
$this->assertEquals($text, $e->getBody());
$this->assertEquals('text content', $e->getTextBody());
$e = new Email();
$e->html('html content');
$this->assertEquals($html, $e->getBody());
$this->assertEquals('html content', $e->getHtmlBody());
$e = new Email();
$e->html('html content');
$e->text('text content');
$this->assertEquals(new AlternativePart($text, $html), $e->getBody());
$e = new Email();
$e->html('html content', 'iso-8859-1');
$e->text('text content', 'iso-8859-1');
$this->assertEquals('iso-8859-1', $e->getTextCharset());
$this->assertEquals('iso-8859-1', $e->getHtmlCharset());
$this->assertEquals(new AlternativePart(new TextPart('text content', 'iso-8859-1'), new TextPart('html content', 'iso-8859-1', 'html')), $e->getBody());
$e = new Email();
$e->attach($file);
$e->text('text content');
$this->assertEquals(new MixedPart($text, $att), $e->getBody());
$e = new Email();
$e->attach($file);
$e->html('html content');
$this->assertEquals(new MixedPart($html, $att), $e->getBody());
$e = new Email();
$e->attach($file);
$this->assertEquals(new MixedPart($att), $e->getBody());
$e = new Email();
$e->html('html content');
$e->text('text content');
$e->attach($file);
$this->assertEquals(new MixedPart(new AlternativePart($text, $html), $att), $e->getBody());
$e = new Email();
$e->html('html content');
$e->text('text content');
$e->attach($file);
$e->attach($image, 'test.gif');
$this->assertEquals(new MixedPart(new AlternativePart($text, $html), $att, $img), $e->getBody());
$e = new Email();
$e->text('text content');
$e->attach($file);
$e->attach($image, 'test.gif');
$this->assertEquals(new MixedPart($text, $att, $img), $e->getBody());
$e = new Email();
$e->html($content = 'html content <img src="test.gif">');
$e->text('text content');
$e->attach($file);
$e->attach($image, 'test.gif');
$fullhtml = new TextPart($content, 'utf-8', 'html');
$this->assertEquals(new MixedPart(new AlternativePart($text, $fullhtml), $att, $img), $e->getBody());
$e = new Email();
$e->html($content = 'html content <img src="cid:test.gif">');
$e->text('text content');
$e->attach($file);
$e->attach($image, 'test.gif');
$fullhtml = new TextPart($content, 'utf-8', 'html');
$inlinedimg = (new DataPart($image, 'test.gif'))->asInline();
$body = $e->getBody();
$this->assertInstanceOf(MixedPart::class, $body);
$this->assertCount(2, $related = $body->getParts());
$this->assertInstanceOf(RelatedPart::class, $related[0]);
$this->assertEquals($att, $related[1]);
$this->assertCount(2, $parts = $related[0]->getParts());
$this->assertInstanceOf(AlternativePart::class, $parts[0]);
$generatedHtml = $parts[0]->getParts()[1];
$this->assertStringContainsString('cid:'.$parts[1]->getContentId(), $generatedHtml->getBody());
$content = 'html content <img src="cid:test.gif">';
$r = fopen('php://memory', 'r+', false);
fwrite($r, $content);
rewind($r);
$e = new Email();
$e->html($r);
// embedding the same image twice results in one image only in the email
$e->embed($image, 'test.gif');
$e->embed($image, 'test.gif');
$body = $e->getBody();
$this->assertInstanceOf(RelatedPart::class, $body);
// 2 parts only, not 3 (text + embedded image once)
$this->assertCount(2, $parts = $body->getParts());
$this->assertStringMatchesFormat('html content <img src=3D"cid:%s@symfony">', $parts[0]->bodyToString());
}
public function testAttachments()
{
$contents = file_get_contents($name = __DIR__.'/Fixtures/mimetypes/test', 'r');
$att = new DataPart($file = fopen($name, 'r'), 'test');
$inline = (new DataPart($contents, 'test'))->asInline();
$e = new Email();
$e->attach($file, 'test');
$e->embed($contents, 'test');
$this->assertEquals([$att, $inline], $e->getAttachments());
$att = DataPart::fromPath($name, 'test');
$inline = DataPart::fromPath($name, 'test')->asInline();
$e = new Email();
$e->attachFromPath($name);
$e->embedFromPath($name);
$this->assertEquals([$att->bodyToString(), $inline->bodyToString()], array_map(function (DataPart $a) { return $a->bodyToString(); }, $e->getAttachments()));
$this->assertEquals([$att->getPreparedHeaders(), $inline->getPreparedHeaders()], array_map(function (DataPart $a) { return $a->getPreparedHeaders(); }, $e->getAttachments()));
}
public function testSerialize()
{
$r = fopen('php://memory', 'r+', false);
fwrite($r, 'Text content');
rewind($r);
$e = new Email();
$e->from('fabien@symfony.com');
$e->text($r);
$e->html($r);
$contents = file_get_contents($name = __DIR__.'/Fixtures/mimetypes/test', 'r');
$file = fopen($name, 'r');
$e->attach($file, 'test');
$expected = clone $e;
$n = unserialize(serialize($e));
$this->assertEquals($expected->getHeaders(), $n->getHeaders());
$this->assertEquals($e->getBody(), $n->getBody());
}
}

158
addons/weliam_smartcity/vendor/symfony/mime/Tests/Encoder/Base64EncoderTest.php

@ -0,0 +1,158 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime\Tests\Encoder;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Mime\Encoder\Base64Encoder;
class Base64EncoderTest extends TestCase
{
/*
There's really no point in testing the entire base64 encoding to the
level QP encoding has been tested. base64_encode() has been in PHP for
years.
*/
public function testInputOutputRatioIs3to4Bytes()
{
/*
RFC 2045, 6.8
The encoding process represents 24-bit groups of input bits as output
strings of 4 encoded characters. Proceeding from left to right, a
24-bit input group is formed by concatenating 3 8bit input groups.
These 24 bits are then treated as 4 concatenated 6-bit groups, each
of which is translated into a single digit in the base64 alphabet.
*/
$encoder = new Base64Encoder();
$this->assertEquals('MTIz', $encoder->encodeString('123'), '3 bytes of input should yield 4 bytes of output');
$this->assertEquals('MTIzNDU2', $encoder->encodeString('123456'), '6 bytes in input should yield 8 bytes of output');
$this->assertEquals('MTIzNDU2Nzg5', $encoder->encodeString('123456789'), '%s: 9 bytes in input should yield 12 bytes of output');
}
public function testPadLength()
{
/*
RFC 2045, 6.8
Special processing is performed if fewer than 24 bits are available
at the end of the data being encoded. A full encoding quantum is
always completed at the end of a body. When fewer than 24 input bits
are available in an input group, zero bits are added (on the right)
to form an integral number of 6-bit groups. Padding at the end of
the data is performed using the "=" character. Since all base64
input is an integral number of octets, only the following cases can
arise: (1) the final quantum of encoding input is an integral
multiple of 24 bits; here, the final unit of encoded output will be
an integral multiple of 4 characters with no "=" padding, (2) the
final quantum of encoding input is exactly 8 bits; here, the final
unit of encoded output will be two characters followed by two "="
padding characters, or (3) the final quantum of encoding input is
exactly 16 bits; here, the final unit of encoded output will be three
characters followed by one "=" padding character.
*/
$encoder = new Base64Encoder();
for ($i = 0; $i < 30; ++$i) {
$input = pack('C', random_int(0, 255));
$this->assertRegExp('~^[a-zA-Z0-9/\+]{2}==$~', $encoder->encodeString($input), 'A single byte should have 2 bytes of padding');
}
for ($i = 0; $i < 30; ++$i) {
$input = pack('C*', random_int(0, 255), random_int(0, 255));
$this->assertRegExp('~^[a-zA-Z0-9/\+]{3}=$~', $encoder->encodeString($input), 'Two bytes should have 1 byte of padding');
}
for ($i = 0; $i < 30; ++$i) {
$input = pack('C*', random_int(0, 255), random_int(0, 255), random_int(0, 255));
$this->assertRegExp('~^[a-zA-Z0-9/\+]{4}$~', $encoder->encodeString($input), 'Three bytes should have no padding');
}
}
public function testMaximumLineLengthIs76Characters()
{
/*
The encoded output stream must be represented in lines of no more
than 76 characters each. All line breaks or other characters not
found in Table 1 must be ignored by decoding software.
*/
$input =
'abcdefghijklmnopqrstuvwxyz'.
'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.
'1234567890'.
'abcdefghijklmnopqrstuvwxyz'.
'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.
'1234567890'.
'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
$output =
'YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQk'.//38
'NERUZHSElKS0xNTk9QUVJTVFVWV1hZWjEyMzQ1'."\r\n".//76 *
'Njc4OTBhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3'.//38
'h5ekFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFla'."\r\n".//76 *
'MTIzNDU2Nzg5MEFCQ0RFRkdISUpLTE1OT1BRUl'.//38
'NUVVZXWFla'; //48
$encoder = new Base64Encoder();
$this->assertEquals($output, $encoder->encodeString($input), 'Lines should be no more than 76 characters');
}
public function testMaximumLineLengthCanBeSpecified()
{
$input =
'abcdefghijklmnopqrstuvwxyz'.
'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.
'1234567890'.
'abcdefghijklmnopqrstuvwxyz'.
'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.
'1234567890'.
'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
$output =
'YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQk'.//38
'NERUZHSElKS0'."\r\n".//50 *
'xNTk9QUVJTVFVWV1hZWjEyMzQ1Njc4OTBhYmNk'.//38
'ZWZnaGlqa2xt'."\r\n".//50 *
'bm9wcXJzdHV2d3h5ekFCQ0RFRkdISUpLTE1OT1'.//38
'BRUlNUVVZXWF'."\r\n".//50 *
'laMTIzNDU2Nzg5MEFCQ0RFRkdISUpLTE1OT1BR'.//38
'UlNUVVZXWFla'; //50 *
$encoder = new Base64Encoder();
$this->assertEquals($output, $encoder->encodeString($input, 'utf-8', 0, 50), 'Lines should be no more than 100 characters');
}
public function testFirstLineLengthCanBeDifferent()
{
$input =
'abcdefghijklmnopqrstuvwxyz'.
'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.
'1234567890'.
'abcdefghijklmnopqrstuvwxyz'.
'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.
'1234567890'.
'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
$output =
'YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQk'.//38
'NERUZHSElKS0xNTk9QU'."\r\n".//57 *
'VJTVFVWV1hZWjEyMzQ1Njc4OTBhYmNkZWZnaGl'.//38
'qa2xtbm9wcXJzdHV2d3h5ekFCQ0RFRkdISUpLT'."\r\n".//76 *
'E1OT1BRUlNUVVZXWFlaMTIzNDU2Nzg5MEFCQ0R'.//38
'FRkdISUpLTE1OT1BRUlNUVVZXWFla'; //67
$encoder = new Base64Encoder();
$this->assertEquals($output, $encoder->encodeString($input, 'utf-8', 19), 'First line offset is 19 so first line should be 57 chars long');
}
}

23
addons/weliam_smartcity/vendor/symfony/mime/Tests/Encoder/Base64MimeHeaderEncoderTest.php

@ -0,0 +1,23 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime\Tests\Encoder;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Mime\Encoder\Base64MimeHeaderEncoder;
class Base64MimeHeaderEncoderTest extends TestCase
{
public function testNameIsB()
{
$this->assertEquals('B', (new Base64MimeHeaderEncoder())->getName());
}
}

213
addons/weliam_smartcity/vendor/symfony/mime/Tests/Encoder/QpEncoderTest.php

@ -0,0 +1,213 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime\Tests\Encoder;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Mime\Encoder\QpEncoder;
class QpEncoderTest extends TestCase
{
/* -- RFC 2045, 6.7 --
(1) (General 8bit representation) Any octet, except a CR or
LF that is part of a CRLF line break of the canonical
(standard) form of the data being encoded, may be
represented by an "=" followed by a two digit
hexadecimal representation of the octet's value. The
digits of the hexadecimal alphabet, for this purpose,
are "0123456789ABCDEF". Uppercase letters must be
used; lowercase letters are not allowed. Thus, for
example, the decimal value 12 (US-ASCII form feed) can
be represented by "=0C", and the decimal value 61 (US-
ASCII EQUAL SIGN) can be represented by "=3D". This
rule must be followed except when the following rules
allow an alternative encoding.
*/
public function testPermittedCharactersAreNotEncoded()
{
/* -- RFC 2045, 6.7 --
(2) (Literal representation) Octets with decimal values of
33 through 60 inclusive, and 62 through 126, inclusive,
MAY be represented as the US-ASCII characters which
correspond to those octets (EXCLAMATION POINT through
LESS THAN, and GREATER THAN through TILDE,
respectively).
*/
$encoder = new QpEncoder();
foreach (array_merge(range(33, 60), range(62, 126)) as $ordinal) {
$char = \chr($ordinal);
$this->assertSame($char, $encoder->encodeString($char));
}
}
public function testWhiteSpaceAtLineEndingIsEncoded()
{
/* -- RFC 2045, 6.7 --
(3) (White Space) Octets with values of 9 and 32 MAY be
represented as US-ASCII TAB (HT) and SPACE characters,
respectively, but MUST NOT be so represented at the end
of an encoded line. Any TAB (HT) or SPACE characters
on an encoded line MUST thus be followed on that line
by a printable character. In particular, an "=" at the
end of an encoded line, indicating a soft line break
(see rule #5) may follow one or more TAB (HT) or SPACE
characters. It follows that an octet with decimal
value 9 or 32 appearing at the end of an encoded line
must be represented according to Rule #1. This rule is
necessary because some MTAs (Message Transport Agents,
programs which transport messages from one user to
another, or perform a portion of such transfers) are
known to pad lines of text with SPACEs, and others are
known to remove "white space" characters from the end
of a line. Therefore, when decoding a Quoted-Printable
body, any trailing white space on a line must be
deleted, as it will necessarily have been added by
intermediate transport agents.
*/
$encoder = new QpEncoder();
$HT = \chr(0x09); // 9
$SPACE = \chr(0x20); // 32
// HT
$string = 'a'.$HT.$HT."\r\n".'b';
$this->assertEquals('a'.$HT.'=09'."\r\n".'b', $encoder->encodeString($string));
// SPACE
$string = 'a'.$SPACE.$SPACE."\r\n".'b';
$this->assertEquals('a'.$SPACE.'=20'."\r\n".'b', $encoder->encodeString($string));
}
public function testCRLFIsLeftAlone()
{
/*
(4) (Line Breaks) A line break in a text body, represented
as a CRLF sequence in the text canonical form, must be
represented by a (RFC 822) line break, which is also a
CRLF sequence, in the Quoted-Printable encoding. Since
the canonical representation of media types other than
text do not generally include the representation of
line breaks as CRLF sequences, no hard line breaks
(i.e. line breaks that are intended to be meaningful
and to be displayed to the user) can occur in the
quoted-printable encoding of such types. Sequences
like "=0D", "=0A", "=0A=0D" and "=0D=0A" will routinely
appear in non-text data represented in quoted-
printable, of course.
Note that many implementations may elect to encode the
local representation of various content types directly
rather than converting to canonical form first,
encoding, and then converting back to local
representation. In particular, this may apply to plain
text material on systems that use newline conventions
other than a CRLF terminator sequence. Such an
implementation optimization is permissible, but only
when the combined canonicalization-encoding step is
equivalent to performing the three steps separately.
*/
$encoder = new QpEncoder();
$string = 'a'."\r\n".'b'."\r\n".'c'."\r\n";
$this->assertEquals($string, $encoder->encodeString($string));
}
public function testLinesLongerThan76CharactersAreSoftBroken()
{
/*
(5) (Soft Line Breaks) The Quoted-Printable encoding
REQUIRES that encoded lines be no more than 76
characters long. If longer lines are to be encoded
with the Quoted-Printable encoding, "soft" line breaks
must be used. An equal sign as the last character on a
encoded line indicates such a non-significant ("soft")
line break in the encoded text.
*/
$encoder = new QpEncoder();
$input = str_repeat('a', 140);
$output = '';
for ($i = 0; $i < 140; ++$i) {
// we read 4 chars at a time (max is 75)
if (18 * 4 /* 72 */ == $i) {
$output .= "=\r\n";
}
$output .= 'a';
}
$this->assertEquals($output, $encoder->encodeString($input));
}
public function testMaxLineLengthCanBeSpecified()
{
$encoder = new QpEncoder();
$input = str_repeat('a', 100);
$output = '';
for ($i = 0; $i < 100; ++$i) {
// we read 4 chars at a time (max is 53)
if (13 * 4 /* 52 */ == $i) {
$output .= "=\r\n";
}
$output .= 'a';
}
$this->assertEquals($output, $encoder->encodeString($input, 'utf-8', 0, 54));
}
public function testBytesBelowPermittedRangeAreEncoded()
{
// According to Rule (1 & 2)
$encoder = new QpEncoder();
foreach (range(0, 32) as $ordinal) {
$char = \chr($ordinal);
$this->assertEquals(sprintf('=%02X', $ordinal), $encoder->encodeString($char));
}
}
public function testDecimalByte61IsEncoded()
{
// According to Rule (1 & 2)
$encoder = new QpEncoder();
$this->assertEquals('=3D', $encoder->encodeString('='));
}
public function testBytesAbovePermittedRangeAreEncoded()
{
// According to Rule (1 & 2)
$encoder = new QpEncoder();
foreach (range(127, 255) as $ordinal) {
$this->assertSame(sprintf('=%02X', $ordinal), $encoder->encodeString(\chr($ordinal), 'iso-8859-1'));
}
}
public function testFirstLineLengthCanBeDifferent()
{
$encoder = new QpEncoder();
$input = str_repeat('a', 140);
$output = '';
for ($i = 0; $i < 140; ++$i) {
// we read 4 chars at a time (max is 54 for the first line and 75 for the second one)
if (13 * 4 == $i || 13 * 4 + 18 * 4 == $i) {
$output .= "=\r\n";
}
$output .= 'a';
}
$this->assertEquals($output, $encoder->encodeString($input, 'utf-8', 22), 'First line should start at offset 22 so can only have max length 54');
}
public function testTextIsPreWrapped()
{
$encoder = new QpEncoder();
$input = str_repeat('a', 70)."\r\n".str_repeat('a', 70)."\r\n".str_repeat('a', 70);
$this->assertEquals($input, $encoder->encodeString($input));
}
}

139
addons/weliam_smartcity/vendor/symfony/mime/Tests/Encoder/QpMimeHeaderEncoderTest.php

@ -0,0 +1,139 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime\Tests\Encoder;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Mime\Encoder\QpMimeHeaderEncoder;
class QpMimeHeaderEncoderTest extends TestCase
{
public function testNameIsQ()
{
$encoder = new QpMimeHeaderEncoder();
$this->assertEquals('Q', $encoder->getName());
}
public function testSpaceAndTabNeverAppear()
{
/* -- RFC 2047, 4.
Only a subset of the printable ASCII characters may be used in
'encoded-text'. Space and tab characters are not allowed, so that
the beginning and end of an 'encoded-word' are obvious.
*/
$encoder = new QpMimeHeaderEncoder();
$this->assertNotRegExp('~[ \t]~', $encoder->encodeString("a \t b"), 'encoded-words in headers cannot contain LWSP as per RFC 2047.');
}
public function testSpaceIsRepresentedByUnderscore()
{
/* -- RFC 2047, 4.2.
(2) The 8-bit hexadecimal value 20 (e.g., ISO-8859-1 SPACE) may be
represented as "_" (underscore, ASCII 95.). (This character may
not pass through some internetwork mail gateways, but its use
will greatly enhance readability of "Q" encoded data with mail
readers that do not support this encoding.) Note that the "_"
always represents hexadecimal 20, even if the SPACE character
occupies a different code position in the character set in use.
*/
$encoder = new QpMimeHeaderEncoder();
$this->assertEquals('a_b', $encoder->encodeString('a b'), 'Spaces can be represented by more readable underscores as per RFC 2047.');
}
public function testEqualsAndQuestionAndUnderscoreAreEncoded()
{
/* -- RFC 2047, 4.2.
(3) 8-bit values which correspond to printable ASCII characters other
than "=", "?", and "_" (underscore), MAY be represented as those
characters. (But see section 5 for restrictions.) In
particular, SPACE and TAB MUST NOT be represented as themselves
within encoded words.
*/
$encoder = new QpMimeHeaderEncoder();
$this->assertEquals('=3D=3F=5F', $encoder->encodeString('=?_'), 'Chars =, ? and _ (underscore) may not appear as per RFC 2047.');
}
public function testParensAndQuotesAreEncoded()
{
/* -- RFC 2047, 5 (2).
A "Q"-encoded 'encoded-word' which appears in a 'comment' MUST NOT
contain the characters "(", ")" or "
*/
$encoder = new QpMimeHeaderEncoder();
$this->assertEquals('=28=22=29', $encoder->encodeString('(")'), 'Chars (, " (DQUOTE) and ) may not appear as per RFC 2047.');
}
public function testOnlyCharactersAllowedInPhrasesAreUsed()
{
/* -- RFC 2047, 5.
(3) As a replacement for a 'word' entity within a 'phrase', for example,
one that precedes an address in a From, To, or Cc header. The ABNF
definition for 'phrase' from RFC 822 thus becomes:
phrase = 1*( encoded-word / word )
In this case the set of characters that may be used in a "Q"-encoded
'encoded-word' is restricted to: <upper and lower case ASCII
letters, decimal digits, "!", "*", "+", "-", "/", "=", and "_"
(underscore, ASCII 95.)>. An 'encoded-word' that appears within a
'phrase' MUST be separated from any adjacent 'word', 'text' or
'special' by 'linear-white-space'.
*/
$allowedBytes = array_merge(
range(\ord('a'), \ord('z')), range(\ord('A'), \ord('Z')),
range(\ord('0'), \ord('9')),
[\ord('!'), \ord('*'), \ord('+'), \ord('-'), \ord('/')]
);
$encoder = new QpMimeHeaderEncoder();
foreach (range(0x00, 0xFF) as $byte) {
$char = pack('C', $byte);
$encodedChar = $encoder->encodeString($char, 'iso-8859-1');
if (\in_array($byte, $allowedBytes)) {
$this->assertEquals($char, $encodedChar, 'Character '.$char.' should not be encoded.');
} elseif (0x20 == $byte) {
// special case
$this->assertEquals('_', $encodedChar, 'Space character should be replaced.');
} else {
$this->assertEquals(sprintf('=%02X', $byte), $encodedChar, 'Byte '.$byte.' should be encoded.');
}
}
}
public function testEqualsNeverAppearsAtEndOfLine()
{
/* -- RFC 2047, 5 (3).
The 'encoded-text' in an 'encoded-word' must be self-contained;
'encoded-text' MUST NOT be continued from one 'encoded-word' to
another. This implies that the 'encoded-text' portion of a "B"
'encoded-word' will be a multiple of 4 characters long; for a "Q"
'encoded-word', any "=" character that appears in the 'encoded-text'
portion will be followed by two hexadecimal characters.
*/
$input = str_repeat('a', 140);
$output = '';
$seq = 0;
for (; $seq < 140; ++$seq) {
// compute the end of line (multiple of 4 chars)
if (18 * 4 === $seq) {
$output .= "\r\n"; // =\r\n
}
$output .= 'a';
}
$encoder = new QpMimeHeaderEncoder();
$this->assertEquals($output, $encoder->encodeString($input));
}
}

129
addons/weliam_smartcity/vendor/symfony/mime/Tests/Encoder/Rfc2231EncoderTest.php

@ -0,0 +1,129 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime\Tests\Encoder;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Mime\Encoder\Rfc2231Encoder;
class Rfc2231EncoderTest extends TestCase
{
private $rfc2045Token = '/^[\x21\x23-\x27\x2A\x2B\x2D\x2E\x30-\x39\x41-\x5A\x5E-\x7E]+$/D';
/* --
This algorithm is described in RFC 2231, but is barely touched upon except
for mentioning bytes can be represented as their octet values (e.g. %20 for
the SPACE character).
The tests here focus on how to use that representation to always generate text
which matches RFC 2045's definition of "token".
*/
public function testEncodingAsciiCharactersProducesValidToken()
{
$string = '';
foreach (range(0x00, 0x7F) as $octet) {
$char = pack('C', $octet);
$string .= $char;
}
$encoder = new Rfc2231Encoder();
$encoded = $encoder->encodeString($string);
foreach (explode("\r\n", $encoded) as $line) {
$this->assertRegExp($this->rfc2045Token, $line, 'Encoder should always return a valid RFC 2045 token.');
}
}
public function testEncodingNonAsciiCharactersProducesValidToken()
{
$string = '';
foreach (range(0x80, 0xFF) as $octet) {
$char = pack('C', $octet);
$string .= $char;
}
$encoder = new Rfc2231Encoder();
$encoded = $encoder->encodeString($string);
foreach (explode("\r\n", $encoded) as $line) {
$this->assertRegExp($this->rfc2045Token, $line, 'Encoder should always return a valid RFC 2045 token.');
}
}
public function testMaximumLineLengthCanBeSet()
{
$string = '';
for ($x = 0; $x < 200; ++$x) {
$char = 'a';
$string .= $char;
}
$encoder = new Rfc2231Encoder();
$encoded = $encoder->encodeString($string, 'utf-8', 0, 75);
// 72 here and not 75 as we read 4 chars at a time
$this->assertEquals(
str_repeat('a', 72)."\r\n".
str_repeat('a', 72)."\r\n".
str_repeat('a', 56),
$encoded,
'Lines should be wrapped at each 72 characters'
);
}
public function testFirstLineCanHaveShorterLength()
{
$string = '';
for ($x = 0; $x < 200; ++$x) {
$char = 'a';
$string .= $char;
}
$encoder = new Rfc2231Encoder();
$encoded = $encoder->encodeString($string, 'utf-8', 24, 72);
$this->assertEquals(
str_repeat('a', 48)."\r\n".
str_repeat('a', 72)."\r\n".
str_repeat('a', 72)."\r\n".
str_repeat('a', 8),
$encoded,
'First line should be 24 bytes shorter than the others.'
);
}
public function testEncodingAndDecodingSamples()
{
$dir = realpath(__DIR__.'/../Fixtures/samples/charsets');
$sampleFp = opendir($dir);
while (false !== $encoding = readdir($sampleFp)) {
if ('.' == substr($encoding, 0, 1)) {
continue;
}
$encoder = new Rfc2231Encoder();
if (is_dir($dir.'/'.$encoding)) {
$fileFp = opendir($dir.'/'.$encoding);
while (false !== $sampleFile = readdir($fileFp)) {
if ('.' == substr($sampleFile, 0, 1)) {
continue;
}
$text = file_get_contents($dir.'/'.$encoding.'/'.$sampleFile);
$encodedText = $encoder->encodeString($text, $encoding);
$this->assertEquals(
urldecode(implode('', explode("\r\n", $encodedText))), $text,
'Encoded string should decode back to original string for sample '.$dir.'/'.$encoding.'/'.$sampleFile
);
}
closedir($fileFp);
}
}
closedir($sampleFp);
}
}

23
addons/weliam_smartcity/vendor/symfony/mime/Tests/FileBinaryMimeTypeGuesserTest.php

@ -0,0 +1,23 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime\Tests;
use Symfony\Component\Mime\FileBinaryMimeTypeGuesser;
use Symfony\Component\Mime\MimeTypeGuesserInterface;
class FileBinaryMimeTypeGuesserTest extends AbstractMimeTypeGuesserTest
{
protected function getGuesser(): MimeTypeGuesserInterface
{
return new FileBinaryMimeTypeGuesser();
}
}

26
addons/weliam_smartcity/vendor/symfony/mime/Tests/FileinfoMimeTypeGuesserTest.php

@ -0,0 +1,26 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Mime\Tests;
use Symfony\Component\Mime\FileinfoMimeTypeGuesser;
use Symfony\Component\Mime\MimeTypeGuesserInterface;
/**
* @requires extension fileinfo
*/
class FileinfoMimeTypeGuesserTest extends AbstractMimeTypeGuesserTest
{
protected function getGuesser(): MimeTypeGuesserInterface
{
return new FileinfoMimeTypeGuesser();
}
}

1
addons/weliam_smartcity/vendor/symfony/mime/Tests/Fixtures/mimetypes/.unknownextension

@ -0,0 +1 @@
f

0
addons/weliam_smartcity/vendor/symfony/mime/Tests/Fixtures/mimetypes/directory/.empty

0
addons/weliam_smartcity/vendor/symfony/mime/Tests/Fixtures/mimetypes/other-file.example

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save