diff --git a/datamodel.combodo-webhook-integration.xml b/datamodel.combodo-webhook-integration.xml index 92b665a..9c7ccc7 100644 --- a/datamodel.combodo-webhook-integration.xml +++ b/datamodel.combodo-webhook-integration.xml @@ -852,22 +852,9 @@ /** @var \DBObject $oTriggeringObject */ $oTriggeringObject = $aContextArgs['this->object()']; - // Check if callback is on the object itself - if(stripos($sCallbackFQCN, '$this->') !== false) - { - $sMethodName = str_ireplace('$this->', '', $sCallbackFQCN); - $payload = $oTriggeringObject->$sMethodName($aContextArgs, $oLog, $this); - } - // Otherwise, check if callback is callable as a static method - elseif(is_callable($sCallbackFQCN)) - { - $payload = call_user_func($sCallbackFQCN, $oTriggeringObject, $aContextArgs, $oLog, $this); - } - // Otherwise, there is a problem - else - { - throw new Exception('Prepare payload callback is not callable ('.$sCallbackFQCN.')'); - } + $oCallBack = new CallbackService($sCallbackFQCN); + $oCallBack->CheckCallbackSignature(get_class($oTriggeringObject), ['array', EventNotification::class, ActionWebhook::class]); + $oCallBack->Invoke($oTriggeringObject, [$aContextArgs, $oLog, $this]); } return $payload; diff --git a/src/Core/Notification/Action/_ActionWebhook.php b/src/Core/Notification/Action/_ActionWebhook.php index e437d8e..d9c849d 100644 --- a/src/Core/Notification/Action/_ActionWebhook.php +++ b/src/Core/Notification/Action/_ActionWebhook.php @@ -6,11 +6,14 @@ use ApplicationContext; use Combodo\iTop\Core\Notification\Action\Webhook\Exception\WebhookInvalidJsonValueException; use Combodo\iTop\Core\WebResponse; +use Combodo\iTop\Service\CallbackService; use Combodo\iTop\Service\WebRequestSender; +use DBObject; use EventWebhook; use Exception; use IssueLog; use MetaModel; +use ReflectionException; use UserRights; use utils; @@ -30,40 +33,29 @@ abstract class _ActionWebhook extends ActionNotification * * @throws \ArchivedObjectException * @throws \CoreException + * @throws ReflectionException + * @throws \Exception */ public static function ExecuteResponseHandler(WebResponse $oResponse, array $aParams) { // Retrieve objects from params - if (! array_key_exists('oTriggeringObject', $aParams) || ! array_key_exists('oActionWebhook', $aParams)) { + if (!array_key_exists('oTriggeringObject', $aParams) || !array_key_exists('oActionWebhook', $aParams)) { IssueLog::Error('Missing parameters in response handler. Expecting at least oTriggeringObject and oActionWebhook', 'console', [ 'oResponse' => $oResponse, 'aParams' => $aParams, ]); throw new Exception('Missing parameters in response handler. See error log for details.'); } - /** @var \DBObject $oTriggeringObject */ - $oTriggeringObject = is_object($aParams['oTriggeringObject']) ? - $aParams['oTriggeringObject'] : - MetaModel::GetObject($aParams['oTriggeringObject']['class'], $aParams['oTriggeringObject']['id'], true, true); + /** @var DBObject $oTriggeringObject */ + $oTriggeringObject = is_object($aParams['oTriggeringObject']) ? + $aParams['oTriggeringObject'] : + MetaModel::GetObject($aParams['oTriggeringObject']['class'], $aParams['oTriggeringObject']['id'], true, true); $oActionWebhook = MetaModel::GetObject($aParams['oActionWebhook']['class'], $aParams['oActionWebhook']['id'], true, true); + $sResponseCallback = $oActionWebhook->Get('process_response_callback'); - // Check if callback is on the object itself - $sResponseCallback = $oActionWebhook->Get('process_response_callback'); - if(stripos($sResponseCallback, '$this->') !== false) - { - $sMethodName = str_ireplace('$this->', '', $sResponseCallback); - $oTriggeringObject->$sMethodName($oResponse, $oActionWebhook); - } - // Otherwise, check if callback is callable as a static method - elseif(is_callable($sResponseCallback)) - { - call_user_func($sResponseCallback, $oTriggeringObject, $oResponse, $oActionWebhook); - } - // Otherwise, there is a problem, we cannot call the callback - elseif(empty($sResponseCallback) === false) - { - throw new Exception('Process response callback is not callable ('.$sResponseCallback.')'); - } + $oCallBack = new CallbackService($sResponseCallback); + $oCallBack->CheckCallbackSignature(get_class($oTriggeringObject), [WebResponse::class, \ActionWebhook::class]); + $oCallBack->Invoke($oTriggeringObject, [$oResponse, $oActionWebhook]); } /** diff --git a/src/Service/CallbackService.php b/src/Service/CallbackService.php new file mode 100644 index 0000000..54937a7 --- /dev/null +++ b/src/Service/CallbackService.php @@ -0,0 +1,109 @@ +CheckCallbackSignature(get_class($oTriggeringObject), [DBObject::class, 'string', 'int']); + * $callbackService->Invoke($oTriggeringObject, ['stringValue', 42]); + * + */ +class CallbackService +{ + private string $sCallBackClassName; + private string $sCallBackMethodName; + private bool $bIsStatic; + + /** + * @throws Exception + */ + public function __construct(string $sCallBackDefinition) + { + if (stripos($sCallBackDefinition, '$this->') !== false) { + $this->sCallBackMethodName = str_ireplace('$this->', '', $sCallBackDefinition); + $this->bIsStatic = false; + $this->sCallBackClassName = ''; // we don't need it for non-static methods + } else { + if (!is_callable($sCallBackDefinition)) { + $sMessageError = "The callback '$sCallBackDefinition' is not valid."; + IssueLog::Error($sMessageError, 'console'); + throw new Exception($sMessageError); + } + $iPos = strrpos($sCallBackDefinition, '::'); + if ($iPos !== false && $iPos > 0) { + $this->sCallBackClassName = substr($sCallBackDefinition, 0, $iPos); + $this->sCallBackMethodName = substr($sCallBackDefinition, $iPos + 2); + $this->bIsStatic = true; + } else { + $sMessageError = "The callback '$sCallBackDefinition' is not a valid static method."; + IssueLog::Error($sMessageError, 'console'); + throw new Exception($sMessageError); + } + } + } + + public function IsStatic(): bool + { + return $this->bIsStatic; + } + + /** + * @throws ReflectionException + * @throws SecurityException + */ + public function CheckCallbackSignature(string $sTriggeringObjectClass, array $aParamsType): void + { + $iParamCount = 0; + if ($this->bIsStatic) { // If the callback is static, we expect the first parameter to be the triggering object type + array_unshift($aParamsType, DBObject::class); + } else { + $this->sCallBackClassName = $sTriggeringObjectClass; + } + $oReflector = new ReflectionClass($this->sCallBackClassName); + $aCallbackParameters = $oReflector->getMethod($this->sCallBackMethodName)->getParameters(); + $iRequiredNumberOfParams = count($aParamsType); + if (count($aCallbackParameters) !== $iRequiredNumberOfParams) { + $sErrorMessage = "The callback method '$this->sCallBackMethodName' of class '$this->sCallBackClassName' must have exactly $iRequiredNumberOfParams parameters."; + IssueLog::Error($sErrorMessage); + throw new SecurityException($sErrorMessage); + } + foreach ($aParamsType as $iParamOrder => $sParamType) { + $oParam = $aCallbackParameters[$iParamOrder]; + if ($oParam->getType() === null) { + $sErrorMessage = "The callback method '$this->sCallBackMethodName' of class '$this->sCallBackClassName' must have type-hinted parameters, but parameter {$oParam->getName()} is not type-hinted."; + IssueLog::Error($sErrorMessage); + throw new SecurityException($sErrorMessage); + } + if ($oParam->getType()->getName() !== $sParamType) { + $sErrorMessage = "The callback method '$this->sCallBackMethodName' of class '$this->sCallBackClassName' must have a parameter of type '$sParamType', but it has {$oParam->getType()->getName()} instead."; + IssueLog::Error($sErrorMessage); + throw new SecurityException($sErrorMessage); + } + } + } + + /** + * @param $oTriggeringObject + * @param array $aParams + * + * @return mixed + */ + public function Invoke($oTriggeringObject, array $aParams): mixed + { + if ($this->bIsStatic) { + return call_user_func_array([$this->sCallBackClassName, $this->sCallBackMethodName], array_merge([$oTriggeringObject], $aParams)); + + } else { + return call_user_func_array([$oTriggeringObject, $this->sCallBackMethodName], $aParams); + } + } +} \ No newline at end of file diff --git a/tests/php-unit-tests/_ActionWebhookTest.php b/tests/php-unit-tests/_ActionWebhookTest.php index 13f35bc..90e7c4d 100644 --- a/tests/php-unit-tests/_ActionWebhookTest.php +++ b/tests/php-unit-tests/_ActionWebhookTest.php @@ -8,15 +8,20 @@ use Combodo\iTop\Core\Notification\Action\_ActionWebhook; use Combodo\iTop\Core\Notification\Action\Webhook\Exception\WebhookInvalidJsonValueException; +use Combodo\iTop\Core\WebResponse; +use ActionWebhook; +use Combodo\iTop\Service\CallbackService; use Combodo\iTop\Test\UnitTest\ItopTestCase; +use DBObject; +use Exception; +use ReflectionException; -class _ActionWebhookTest extends ItopTestCase { - protected function setUp(): void { +class _ActionWebhookTest extends ItopTestCase +{ + protected function setUp(): void + { parent::setUp(); - - // no datamodel loaded so we need to include module file manually - $this->RequireOnceItopFile('env-production/combodo-webhook-integration/src/Core/Notification/Action/_ActionWebhook.php'); - $this->RequireOnceItopFile('env-production/combodo-webhook-integration/src/Core/Notification/Action/Webhook/Exception/WebhookInvalidJsonValueException.php'); + $this->RequireOnceItopFile('env-production/combodo-webhook-integration/vendor/autoload.php'); } /** @@ -58,4 +63,172 @@ public function IsJsonValidProvider() { 'invalid array' => ['{foo:bar}', true], ]; } + + /** + * @return void + * @dataProvider CheckCallbackSignatureTestProvider + * @throws ReflectionException + * @throws Exception + */ + public function testCheckCallbackSignature(string $sResponseCallback, $bExpectedException, $sErrorMessage) + { + if ($bExpectedException) { + $this->expectException(\SecurityException::class); + $this->expectExceptionMessage($sErrorMessage); + } else { + $this->expectNotToPerformAssertions(); + } + $oCallBackService = new CallbackService($sResponseCallback); + if ($oCallBackService->IsStatic()) { + $oCallBackService->CheckCallbackSignature(DBObject::class, ['Combodo\iTop\Core\WebResponse', 'ActionWebhook']); + } else { + $oCallBackService->CheckCallbackSignature($this::class, ['Combodo\iTop\Core\WebResponse', 'ActionWebhook']); + } + } + + public function CheckCallbackSignatureTestProvider(): array + { + return [ + 'Check callback signature with no parameters' => [ + 'sResponseCallback' => _ActionWebhookTest::class.'::CallBackWebhookNoParams', + 'expectedException' => true, + 'sErrorMessage' => 'The callback method \'CallBackWebhookNoParams\' of class \'Combodo\iTop\Test\UnitTest\Core\_ActionWebhookTest\' must have exactly 3 parameters.', + ], + 'Check callback signature with no parameters on object' => [ + 'sResponseCallback' => '$this->CallBackWebhookNoParamsOnObject', + 'expectedException' => true, + 'sErrorMessage' => 'The callback method \'CallBackWebhookNoParamsOnObject\' of class \'Combodo\iTop\Test\UnitTest\Core\_ActionWebhookTest\' must have exactly 2 parameters.', + ], + 'Check callback signature with one parameter' => [ + 'sResponseCallback' => _ActionWebhookTest::class.'::CallBackWebhookOneParam', + 'expectedException' => true, + 'sErrorMessage' => 'The callback method \'CallBackWebhookOneParam\' of class \'Combodo\iTop\Test\UnitTest\Core\_ActionWebhookTest\' must have exactly 3 parameters.', + ], + 'Check callback signature with one parameter on object' => [ + 'sResponseCallback' => '$this->CallBackWebhookOneParamOnObject', + 'expectedException' => true, + 'sErrorMessage' => 'The callback method \'CallBackWebhookOneParamOnObject\' of class \'Combodo\iTop\Test\UnitTest\Core\_ActionWebhookTest\' must have exactly 2 parameters.', + ], + 'Check callback signature with no type' => [ + 'sResponseCallback' => _ActionWebhookTest::class.'::CallBackWebhookThreeUntypedParams', + 'expectedException' => true, + 'sErrorMessage' => "The callback method 'CallBackWebhookThreeUntypedParams' of class 'Combodo\iTop\Test\UnitTest\Core\_ActionWebhookTest' must have type-hinted parameters, but parameter oDBObject is not type-hinted.", + ], + 'Check callback signature with no type on object' => [ + 'sResponseCallback' => '$this->CallBackWebhookTwoUntypedParamsOnObject', + 'expectedException' => true, + 'sErrorMessage' => "The callback method 'CallBackWebhookTwoUntypedParamsOnObject' of class 'Combodo\iTop\Test\UnitTest\Core\_ActionWebhookTest' must have type-hinted parameters, but parameter oWebResponse is not type-hinted.", + ], + 'Check callback signature with wrong type' => [ + 'sResponseCallback' => _ActionWebhookTest::class.'::CallBackWebhookThreeParamsWithWrongType', + 'expectedException' => true, + 'sErrorMessage' => "The callback method 'CallBackWebhookThreeParamsWithWrongType' of class 'Combodo\iTop\Test\UnitTest\Core\_ActionWebhookTest' must have a parameter of type 'DBObject', but it has int instead.", + ], + 'Check callback signature with wrong type on object' => [ + 'sResponseCallback' => '$this->CallBackWebhookTwoParamsWithWrongTypeOnObject', + 'expectedException' => true, + 'sErrorMessage' => "The callback method 'CallBackWebhookTwoParamsWithWrongTypeOnObject' of class 'Combodo\iTop\Test\UnitTest\Core\_ActionWebhookTest' must have a parameter of type 'Combodo\iTop\Core\WebResponse', but it has int instead.", + ], + 'Check callback signature with correct type but incorrect order' => [ + 'sResponseCallback' => _ActionWebhookTest::class.'::CallBackWebhookThreeParamsCorrectButWrongOrder', + 'expectedException' => true, + 'sErrorMessage' => "Combodo\iTop\Test\UnitTest\Core\_ActionWebhookTest' must have a parameter of type 'DBObject', but it has Combodo\iTop\Core\WebResponse instead.", + ], + 'Check callback signature with correct type but incorrect order on object' => [ + 'sResponseCallback' => '$this->CallBackWebhookTwoParamsCorrectButWrongOrderOnObject', + 'expectedException' => true, + 'sErrorMessage' => "Combodo\iTop\Test\UnitTest\Core\_ActionWebhookTest' must have a parameter of type 'Combodo\iTop\Core\WebResponse', but it has ActionWebhook instead.", + ], + 'Check callback signature with correct type' => [ + 'sResponseCallback' => _ActionWebhookTest::class.'::CallBackWebhookThreeParamsCorrect', + 'expectedException' => false, + 'sErrorMessage' => '', + ], + 'Check callback signature with correct type on object' => [ + 'sResponseCallback' => '$this->CallBackWebhookTwoParamsCorrectOnObject', + 'expectedException' => false, + 'sErrorMessage' => '', + ], + 'Check callback signature with correct type and namespace' => [ + 'sResponseCallback' => _ActionWebhookTest::class.'::CallBackWebhookThreeParamsCorrectWithNamespace', + 'expectedException' => false, + 'sErrorMessage' => '', + ], + 'Check callback signature with correct type and namespace on object' => [ + 'sResponseCallback' => '$this->CallBackWebhookTwoParamsCorrectWithNamespaceOnObject', + 'expectedException' => false, + 'sErrorMessage' => '', + ], + ]; + } + + public static function CallBackWebhookNoParams() + { + // This method is intentionally left empty to test the callback signature + } + + public static function CallBackWebhookOneParam(int $i) + { + // This method is intentionally left empty to test the callback signature + } + + public static function CallBackWebhookThreeUntypedParams($oDBObject, $oWebResponse, $oActionWebhook) + { + // This method is intentionally left empty to test the callback signature + } + + public static function CallBackWebhookThreeParamsWithWrongType(int $oDBObject, $oWebResponse, $oActionWebhook) + { + // This method is intentionally left empty to test the callback signature + } + + public static function CallBackWebhookThreeParamsCorrectButWrongOrder(WebResponse $oWebResponse, DBObject $oDBObject, ActionWebhook $oActionWebhook) + { + // This method is intentionally left empty to test the callback signature + } + + public static function CallBackWebhookThreeParamsCorrect(DBObject $oDBObject, WebResponse $oWebResponse, ActionWebhook $oActionWebhook) + { + // This method is intentionally left empty to test the callback signature + } + + public static function CallBackWebhookThreeParamsCorrectWithNamespace(\DBObject $oDBObject, \Combodo\iTop\Core\WebResponse $oWebResponse, \ActionWebhook $oActionWebhook) + { + // This method is intentionally left empty to test the callback signature + } + + private function CallBackWebhookNoParamsOnObject() + { + // This method is intentionally left empty to test the callback signature + } + + private function CallBackWebhookOneParamOnObject(int $i) + { + // This method is intentionally left empty to test the callback signature + } + + private function CallBackWebhookTwoUntypedParamsOnObject($oWebResponse, $oActionWebhook) + { + // This method is intentionally left empty to test the callback signature + } + + private function CallBackWebhookTwoParamsWithWrongTypeOnObject(int $oWebResponse, $oActionWebhook) + { + // This method is intentionally left empty to test the callback signature + } + + private function CallBackWebhookTwoParamsCorrectButWrongOrderOnObject(ActionWebhook $oActionWebhook, WebResponse $oWebResponse) + { + // This method is intentionally left empty to test the callback signature + } + + private function CallBackWebhookTwoParamsCorrectOnObject( WebResponse $oWebResponse, ActionWebhook $oActionWebhook) + { + // This method is intentionally left empty to test the callback signature + } + + private function CallBackWebhookTwoParamsCorrectWithNamespaceOnObject(\Combodo\iTop\Core\WebResponse $oWebResponse, \ActionWebhook $oActionWebhook) + { + // This method is intentionally left empty to test the callback signature + } } diff --git a/vendor/autoload.php b/vendor/autoload.php index 550ec59..dc1c8d0 100644 --- a/vendor/autoload.php +++ b/vendor/autoload.php @@ -2,6 +2,24 @@ // autoload.php @generated by Composer +if (PHP_VERSION_ID < 50600) { + if (!headers_sent()) { + header('HTTP/1.1 500 Internal Server Error'); + } + $err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL; + if (!ini_get('display_errors')) { + if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') { + fwrite(STDERR, $err); + } elseif (!headers_sent()) { + echo $err; + } + } + trigger_error( + $err, + E_USER_ERROR + ); +} + require_once __DIR__ . '/composer/autoload_real.php'; return ComposerAutoloaderInit5c648c5cddb3c29c87aec82f31f7e556::getLoader(); diff --git a/vendor/composer/ClassLoader.php b/vendor/composer/ClassLoader.php index 0cd6055..7824d8f 100644 --- a/vendor/composer/ClassLoader.php +++ b/vendor/composer/ClassLoader.php @@ -42,35 +42,37 @@ */ class ClassLoader { - /** @var ?string */ + /** @var \Closure(string):void */ + private static $includeFile; + + /** @var string|null */ private $vendorDir; // PSR-4 /** - * @var array[] - * @psalm-var array> + * @var array> */ private $prefixLengthsPsr4 = array(); /** - * @var array[] - * @psalm-var array> + * @var array> */ private $prefixDirsPsr4 = array(); /** - * @var array[] - * @psalm-var array + * @var list */ private $fallbackDirsPsr4 = array(); // PSR-0 /** - * @var array[] - * @psalm-var array> + * List of PSR-0 prefixes + * + * Structured as array('F (first letter)' => array('Foo\Bar (full prefix)' => array('path', 'path2'))) + * + * @var array>> */ private $prefixesPsr0 = array(); /** - * @var array[] - * @psalm-var array + * @var list */ private $fallbackDirsPsr0 = array(); @@ -78,8 +80,7 @@ class ClassLoader private $useIncludePath = false; /** - * @var string[] - * @psalm-var array + * @var array */ private $classMap = array(); @@ -87,29 +88,29 @@ class ClassLoader private $classMapAuthoritative = false; /** - * @var bool[] - * @psalm-var array + * @var array */ private $missingClasses = array(); - /** @var ?string */ + /** @var string|null */ private $apcuPrefix; /** - * @var self[] + * @var array */ private static $registeredLoaders = array(); /** - * @param ?string $vendorDir + * @param string|null $vendorDir */ public function __construct($vendorDir = null) { $this->vendorDir = $vendorDir; + self::initializeIncludeClosure(); } /** - * @return string[] + * @return array> */ public function getPrefixes() { @@ -121,8 +122,7 @@ public function getPrefixes() } /** - * @return array[] - * @psalm-return array> + * @return array> */ public function getPrefixesPsr4() { @@ -130,8 +130,7 @@ public function getPrefixesPsr4() } /** - * @return array[] - * @psalm-return array + * @return list */ public function getFallbackDirs() { @@ -139,8 +138,7 @@ public function getFallbackDirs() } /** - * @return array[] - * @psalm-return array + * @return list */ public function getFallbackDirsPsr4() { @@ -148,8 +146,7 @@ public function getFallbackDirsPsr4() } /** - * @return string[] Array of classname => path - * @psalm-var array + * @return array Array of classname => path */ public function getClassMap() { @@ -157,8 +154,7 @@ public function getClassMap() } /** - * @param string[] $classMap Class to filename map - * @psalm-param array $classMap + * @param array $classMap Class to filename map * * @return void */ @@ -175,24 +171,25 @@ public function addClassMap(array $classMap) * Registers a set of PSR-0 directories for a given prefix, either * appending or prepending to the ones previously set for this prefix. * - * @param string $prefix The prefix - * @param string[]|string $paths The PSR-0 root directories - * @param bool $prepend Whether to prepend the directories + * @param string $prefix The prefix + * @param list|string $paths The PSR-0 root directories + * @param bool $prepend Whether to prepend the directories * * @return void */ public function add($prefix, $paths, $prepend = false) { + $paths = (array) $paths; if (!$prefix) { if ($prepend) { $this->fallbackDirsPsr0 = array_merge( - (array) $paths, + $paths, $this->fallbackDirsPsr0 ); } else { $this->fallbackDirsPsr0 = array_merge( $this->fallbackDirsPsr0, - (array) $paths + $paths ); } @@ -201,19 +198,19 @@ public function add($prefix, $paths, $prepend = false) $first = $prefix[0]; if (!isset($this->prefixesPsr0[$first][$prefix])) { - $this->prefixesPsr0[$first][$prefix] = (array) $paths; + $this->prefixesPsr0[$first][$prefix] = $paths; return; } if ($prepend) { $this->prefixesPsr0[$first][$prefix] = array_merge( - (array) $paths, + $paths, $this->prefixesPsr0[$first][$prefix] ); } else { $this->prefixesPsr0[$first][$prefix] = array_merge( $this->prefixesPsr0[$first][$prefix], - (array) $paths + $paths ); } } @@ -222,9 +219,9 @@ public function add($prefix, $paths, $prepend = false) * Registers a set of PSR-4 directories for a given namespace, either * appending or prepending to the ones previously set for this namespace. * - * @param string $prefix The prefix/namespace, with trailing '\\' - * @param string[]|string $paths The PSR-4 base directories - * @param bool $prepend Whether to prepend the directories + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param list|string $paths The PSR-4 base directories + * @param bool $prepend Whether to prepend the directories * * @throws \InvalidArgumentException * @@ -232,17 +229,18 @@ public function add($prefix, $paths, $prepend = false) */ public function addPsr4($prefix, $paths, $prepend = false) { + $paths = (array) $paths; if (!$prefix) { // Register directories for the root namespace. if ($prepend) { $this->fallbackDirsPsr4 = array_merge( - (array) $paths, + $paths, $this->fallbackDirsPsr4 ); } else { $this->fallbackDirsPsr4 = array_merge( $this->fallbackDirsPsr4, - (array) $paths + $paths ); } } elseif (!isset($this->prefixDirsPsr4[$prefix])) { @@ -252,18 +250,18 @@ public function addPsr4($prefix, $paths, $prepend = false) throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); } $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; - $this->prefixDirsPsr4[$prefix] = (array) $paths; + $this->prefixDirsPsr4[$prefix] = $paths; } elseif ($prepend) { // Prepend directories for an already registered namespace. $this->prefixDirsPsr4[$prefix] = array_merge( - (array) $paths, + $paths, $this->prefixDirsPsr4[$prefix] ); } else { // Append directories for an already registered namespace. $this->prefixDirsPsr4[$prefix] = array_merge( $this->prefixDirsPsr4[$prefix], - (array) $paths + $paths ); } } @@ -272,8 +270,8 @@ public function addPsr4($prefix, $paths, $prepend = false) * Registers a set of PSR-0 directories for a given prefix, * replacing any others previously set for this prefix. * - * @param string $prefix The prefix - * @param string[]|string $paths The PSR-0 base directories + * @param string $prefix The prefix + * @param list|string $paths The PSR-0 base directories * * @return void */ @@ -290,8 +288,8 @@ public function set($prefix, $paths) * Registers a set of PSR-4 directories for a given namespace, * replacing any others previously set for this namespace. * - * @param string $prefix The prefix/namespace, with trailing '\\' - * @param string[]|string $paths The PSR-4 base directories + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param list|string $paths The PSR-4 base directories * * @throws \InvalidArgumentException * @@ -425,7 +423,8 @@ public function unregister() public function loadClass($class) { if ($file = $this->findFile($class)) { - includeFile($file); + $includeFile = self::$includeFile; + $includeFile($file); return true; } @@ -476,9 +475,9 @@ public function findFile($class) } /** - * Returns the currently registered loaders indexed by their corresponding vendor directories. + * Returns the currently registered loaders keyed by their corresponding vendor directories. * - * @return self[] + * @return array */ public static function getRegisteredLoaders() { @@ -555,18 +554,26 @@ private function findFileWithExtension($class, $ext) return false; } -} -/** - * Scope isolated include. - * - * Prevents access to $this/self from included files. - * - * @param string $file - * @return void - * @private - */ -function includeFile($file) -{ - include $file; + /** + * @return void + */ + private static function initializeIncludeClosure() + { + if (self::$includeFile !== null) { + return; + } + + /** + * Scope isolated include. + * + * Prevents access to $this/self from included files. + * + * @param string $file + * @return void + */ + self::$includeFile = \Closure::bind(static function($file) { + include $file; + }, null, null); + } } diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php index 8b22278..b01cb33 100644 --- a/vendor/composer/autoload_classmap.php +++ b/vendor/composer/autoload_classmap.php @@ -2,7 +2,7 @@ // autoload_classmap.php @generated by Composer -$vendorDir = dirname(dirname(__FILE__)); +$vendorDir = dirname(__DIR__); $baseDir = dirname($vendorDir); return array( @@ -10,6 +10,7 @@ 'Combodo\\iTop\\Core\\Notification\\Action\\_ActionWebhook' => $baseDir . '/src/Core/Notification/Action/_ActionWebhook.php', 'Combodo\\iTop\\Core\\WebRequest' => $baseDir . '/src/Core/WebRequest.php', 'Combodo\\iTop\\Core\\WebResponse' => $baseDir . '/src/Core/WebResponse.php', + 'Combodo\\iTop\\Service\\CallbackService' => $baseDir . '/src/Service/CallbackService.php', 'Combodo\\iTop\\Service\\WebRequestSender' => $baseDir . '/src/Service/WebRequestSender.php', 'Combodo\\iTop\\Service\\WebRequestService' => $baseDir . '/src/Service/WebRequestService.php', 'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php', diff --git a/vendor/composer/autoload_namespaces.php b/vendor/composer/autoload_namespaces.php index b7fc012..15a2ff3 100644 --- a/vendor/composer/autoload_namespaces.php +++ b/vendor/composer/autoload_namespaces.php @@ -2,7 +2,7 @@ // autoload_namespaces.php @generated by Composer -$vendorDir = dirname(dirname(__FILE__)); +$vendorDir = dirname(__DIR__); $baseDir = dirname($vendorDir); return array( diff --git a/vendor/composer/autoload_psr4.php b/vendor/composer/autoload_psr4.php index 51ca060..6d2ed79 100644 --- a/vendor/composer/autoload_psr4.php +++ b/vendor/composer/autoload_psr4.php @@ -2,7 +2,7 @@ // autoload_psr4.php @generated by Composer -$vendorDir = dirname(dirname(__FILE__)); +$vendorDir = dirname(__DIR__); $baseDir = dirname($vendorDir); return array( diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php index b5d4a4b..2d077eb 100644 --- a/vendor/composer/autoload_real.php +++ b/vendor/composer/autoload_real.php @@ -23,20 +23,11 @@ public static function getLoader() } spl_autoload_register(array('ComposerAutoloaderInit5c648c5cddb3c29c87aec82f31f7e556', 'loadClassLoader'), true, true); - self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__))); + self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__)); spl_autoload_unregister(array('ComposerAutoloaderInit5c648c5cddb3c29c87aec82f31f7e556', 'loadClassLoader')); - $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded()); - if ($useStaticLoader) { - require __DIR__ . '/autoload_static.php'; - - call_user_func(\Composer\Autoload\ComposerStaticInit5c648c5cddb3c29c87aec82f31f7e556::getInitializer($loader)); - } else { - $classMap = require __DIR__ . '/autoload_classmap.php'; - if ($classMap) { - $loader->addClassMap($classMap); - } - } + require __DIR__ . '/autoload_static.php'; + call_user_func(\Composer\Autoload\ComposerStaticInit5c648c5cddb3c29c87aec82f31f7e556::getInitializer($loader)); $loader->setClassMapAuthoritative(true); $loader->register(true); diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php index 3867bd8..f0c76e3 100644 --- a/vendor/composer/autoload_static.php +++ b/vendor/composer/autoload_static.php @@ -25,6 +25,7 @@ class ComposerStaticInit5c648c5cddb3c29c87aec82f31f7e556 'Combodo\\iTop\\Core\\Notification\\Action\\_ActionWebhook' => __DIR__ . '/../..' . '/src/Core/Notification/Action/_ActionWebhook.php', 'Combodo\\iTop\\Core\\WebRequest' => __DIR__ . '/../..' . '/src/Core/WebRequest.php', 'Combodo\\iTop\\Core\\WebResponse' => __DIR__ . '/../..' . '/src/Core/WebResponse.php', + 'Combodo\\iTop\\Service\\CallbackService' => __DIR__ . '/../..' . '/src/Service/CallbackService.php', 'Combodo\\iTop\\Service\\WebRequestSender' => __DIR__ . '/../..' . '/src/Service/WebRequestSender.php', 'Combodo\\iTop\\Service\\WebRequestService' => __DIR__ . '/../..' . '/src/Service/WebRequestService.php', 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',