diff --git a/ext/pimple/pimple.c b/ext/pimple/pimple.c index b2dd6176..c80499b3 100644 --- a/ext/pimple/pimple.c +++ b/ext/pimple/pimple.c @@ -715,10 +715,16 @@ PHP_METHOD(Pimple, extend) RETURN_NULL(); } - if (value->type != PIMPLE_IS_SERVICE || zend_hash_index_exists(&pobj->protected, value->handle_num)) { + if (value->type != PIMPLE_IS_SERVICE) { pimple_throw_exception_string(pimple_ce_InvalidServiceIdentifierException, Z_STRVAL_P(offset), Z_STRLEN_P(offset) TSRMLS_CC); RETURN_NULL(); } + if (zend_hash_index_exists(&pobj->protected, value->handle_num)) { + int er = EG(error_reporting); + EG(error_reporting) = 0; + php_error(E_DEPRECATED, "How Pimple behaves when extending protected closures will be fixed in Pimple 4. Are you sure \"%s\" should be protected?", Z_STRVAL_P(offset)); + EG(error_reporting) = er; + } break; case IS_DOUBLE: case IS_BOOL: @@ -733,11 +739,17 @@ PHP_METHOD(Pimple, extend) pimple_throw_exception_string(pimple_ce_UnknownIdentifierException, Z_STRVAL_P(offset), Z_STRLEN_P(offset) TSRMLS_CC); RETURN_NULL(); } - if (value->type != PIMPLE_IS_SERVICE || zend_hash_index_exists(&pobj->protected, value->handle_num)) { + if (value->type != PIMPLE_IS_SERVICE) { convert_to_string(offset); pimple_throw_exception_string(pimple_ce_InvalidServiceIdentifierException, Z_STRVAL_P(offset), Z_STRLEN_P(offset) TSRMLS_CC); RETURN_NULL(); } + if (zend_hash_index_exists(&pobj->protected, value->handle_num)) { + int er = EG(error_reporting); + EG(error_reporting) = 0; + php_error(E_DEPRECATED, "How Pimple behaves when extending protected closures will be fixed in Pimple 4. Are you sure \"%ld\" should be protected?", index); + EG(error_reporting) = er; + } break; case IS_NULL: default: diff --git a/src/Pimple/Container.php b/src/Pimple/Container.php index 73a4ebcd..e761964b 100644 --- a/src/Pimple/Container.php +++ b/src/Pimple/Container.php @@ -241,10 +241,14 @@ public function extend($id, $callable) throw new FrozenServiceException($id); } - if (!is_object($this->values[$id]) || !method_exists($this->values[$id], '__invoke') || isset($this->protected[$this->values[$id]])) { + if (!is_object($this->values[$id]) || !method_exists($this->values[$id], '__invoke')) { throw new InvalidServiceIdentifierException($id); } + if (isset($this->protected[$this->values[$id]])) { + @trigger_error(sprintf('How Pimple behaves when extending protected closures will be fixed in Pimple 4. Are you sure "%s" should be protected?', $id), E_USER_DEPRECATED); + } + if (!is_object($callable) || !method_exists($callable, '__invoke')) { throw new ExpectedInvokableException('Extension service definition is not a Closure or invokable object.'); } diff --git a/src/Pimple/Tests/PimpleTest.php b/src/Pimple/Tests/PimpleTest.php index 09a640f7..acb66e00 100644 --- a/src/Pimple/Tests/PimpleTest.php +++ b/src/Pimple/Tests/PimpleTest.php @@ -392,17 +392,21 @@ public function testLegacyExtendFailsForKeysNotContainingServiceDefinitions($ser } /** - * @expectedException \Pimple\Exception\InvalidServiceIdentifierException - * @expectedExceptionMessage Identifier "foo" does not contain an object definition. + * @group legacy + * @expectedDeprecation How Pimple behaves when extending protected closures will be fixed in Pimple 4. Are you sure "foo" should be protected? */ - public function testExtendFailsIfEntryIsProtected() + public function testExtendingProtectedClosureDeprecation() { $pimple = new Container(); $pimple['foo'] = $pimple->protect(function () { return 'bar'; }); - $pimple->extend('foo', function () {}); + $pimple->extend('foo', function ($value) { + return $value.'-baz'; + }); + + $this->assertSame('bar-baz', $pimple['foo']); } /**