Merge branch '2.8' into 3.4
* 2.8: Command::addOption should allow int in $default [Form] Minor fixes in docs and cs [Form] Fixed empty data for compound date types
This commit is contained in:
commit
4f18e76a0b
@ -387,11 +387,11 @@ class Command
|
|||||||
/**
|
/**
|
||||||
* Adds an option.
|
* Adds an option.
|
||||||
*
|
*
|
||||||
* @param string $name The option name
|
* @param string $name The option name
|
||||||
* @param string|array $shortcut The shortcuts, can be null, a string of shortcuts delimited by | or an array of shortcuts
|
* @param string|array $shortcut The shortcuts, can be null, a string of shortcuts delimited by | or an array of shortcuts
|
||||||
* @param int|null $mode The option mode: One of the VALUE_* constants
|
* @param int|null $mode The option mode: One of the VALUE_* constants
|
||||||
* @param string $description A description text
|
* @param string $description A description text
|
||||||
* @param string|string[]|bool|null $default The default value (must be null for self::VALUE_NONE)
|
* @param string|string[]|int|bool|null $default The default value (must be null for self::VALUE_NONE)
|
||||||
*
|
*
|
||||||
* @throws InvalidArgumentException If option mode is invalid or incompatible
|
* @throws InvalidArgumentException If option mode is invalid or incompatible
|
||||||
*
|
*
|
||||||
|
@ -90,6 +90,9 @@ class DateTimeType extends AbstractType
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// when the form is compound the entries of the array are ignored in favor of children data
|
||||||
|
// so we need to handle the cascade setting here
|
||||||
|
$emptyData = $builder->getEmptyData() ?: array();
|
||||||
// Only pass a subset of the options to children
|
// Only pass a subset of the options to children
|
||||||
$dateOptions = array_intersect_key($options, array_flip(array(
|
$dateOptions = array_intersect_key($options, array_flip(array(
|
||||||
'years',
|
'years',
|
||||||
@ -104,6 +107,10 @@ class DateTimeType extends AbstractType
|
|||||||
'invalid_message_parameters',
|
'invalid_message_parameters',
|
||||||
)));
|
)));
|
||||||
|
|
||||||
|
if (isset($emptyData['date'])) {
|
||||||
|
$dateOptions['empty_data'] = $emptyData['date'];
|
||||||
|
}
|
||||||
|
|
||||||
$timeOptions = array_intersect_key($options, array_flip(array(
|
$timeOptions = array_intersect_key($options, array_flip(array(
|
||||||
'hours',
|
'hours',
|
||||||
'minutes',
|
'minutes',
|
||||||
@ -119,6 +126,10 @@ class DateTimeType extends AbstractType
|
|||||||
'invalid_message_parameters',
|
'invalid_message_parameters',
|
||||||
)));
|
)));
|
||||||
|
|
||||||
|
if (isset($emptyData['time'])) {
|
||||||
|
$timeOptions['empty_data'] = $emptyData['time'];
|
||||||
|
}
|
||||||
|
|
||||||
if (false === $options['label']) {
|
if (false === $options['label']) {
|
||||||
$dateOptions['label'] = false;
|
$dateOptions['label'] = false;
|
||||||
$timeOptions['label'] = false;
|
$timeOptions['label'] = false;
|
||||||
@ -224,6 +235,9 @@ class DateTimeType extends AbstractType
|
|||||||
// this option.
|
// this option.
|
||||||
'data_class' => null,
|
'data_class' => null,
|
||||||
'compound' => $compound,
|
'compound' => $compound,
|
||||||
|
'empty_data' => function (Options $options) {
|
||||||
|
return $options['compound'] ? array() : '';
|
||||||
|
},
|
||||||
));
|
));
|
||||||
|
|
||||||
// Don't add some defaults in order to preserve the defaults
|
// Don't add some defaults in order to preserve the defaults
|
||||||
|
@ -75,7 +75,21 @@ class DateType extends AbstractType
|
|||||||
|
|
||||||
$yearOptions = $monthOptions = $dayOptions = array(
|
$yearOptions = $monthOptions = $dayOptions = array(
|
||||||
'error_bubbling' => true,
|
'error_bubbling' => true,
|
||||||
|
'empty_data' => '',
|
||||||
);
|
);
|
||||||
|
// when the form is compound the entries of the array are ignored in favor of children data
|
||||||
|
// so we need to handle the cascade setting here
|
||||||
|
$emptyData = $builder->getEmptyData() ?: array();
|
||||||
|
|
||||||
|
if (isset($emptyData['year'])) {
|
||||||
|
$yearOptions['empty_data'] = $emptyData['year'];
|
||||||
|
}
|
||||||
|
if (isset($emptyData['month'])) {
|
||||||
|
$monthOptions['empty_data'] = $emptyData['month'];
|
||||||
|
}
|
||||||
|
if (isset($emptyData['day'])) {
|
||||||
|
$dayOptions['empty_data'] = $emptyData['day'];
|
||||||
|
}
|
||||||
|
|
||||||
if (isset($options['invalid_message'])) {
|
if (isset($options['invalid_message'])) {
|
||||||
$dayOptions['invalid_message'] = $options['invalid_message'];
|
$dayOptions['invalid_message'] = $options['invalid_message'];
|
||||||
@ -262,6 +276,9 @@ class DateType extends AbstractType
|
|||||||
// this option.
|
// this option.
|
||||||
'data_class' => null,
|
'data_class' => null,
|
||||||
'compound' => $compound,
|
'compound' => $compound,
|
||||||
|
'empty_data' => function (Options $options) {
|
||||||
|
return $options['compound'] ? array() : '';
|
||||||
|
},
|
||||||
'choice_translation_domain' => false,
|
'choice_translation_domain' => false,
|
||||||
));
|
));
|
||||||
|
|
||||||
|
@ -70,7 +70,15 @@ class TimeType extends AbstractType
|
|||||||
} else {
|
} else {
|
||||||
$hourOptions = $minuteOptions = $secondOptions = array(
|
$hourOptions = $minuteOptions = $secondOptions = array(
|
||||||
'error_bubbling' => true,
|
'error_bubbling' => true,
|
||||||
|
'empty_data' => '',
|
||||||
);
|
);
|
||||||
|
// when the form is compound the entries of the array are ignored in favor of children data
|
||||||
|
// so we need to handle the cascade setting here
|
||||||
|
$emptyData = $builder->getEmptyData() ?: array();
|
||||||
|
|
||||||
|
if (isset($emptyData['hour'])) {
|
||||||
|
$hourOptions['empty_data'] = $emptyData['hour'];
|
||||||
|
}
|
||||||
|
|
||||||
if (isset($options['invalid_message'])) {
|
if (isset($options['invalid_message'])) {
|
||||||
$hourOptions['invalid_message'] = $options['invalid_message'];
|
$hourOptions['invalid_message'] = $options['invalid_message'];
|
||||||
@ -135,10 +143,16 @@ class TimeType extends AbstractType
|
|||||||
$builder->add('hour', self::$widgets[$options['widget']], $hourOptions);
|
$builder->add('hour', self::$widgets[$options['widget']], $hourOptions);
|
||||||
|
|
||||||
if ($options['with_minutes']) {
|
if ($options['with_minutes']) {
|
||||||
|
if (isset($emptyData['minute'])) {
|
||||||
|
$minuteOptions['empty_data'] = $emptyData['minute'];
|
||||||
|
}
|
||||||
$builder->add('minute', self::$widgets[$options['widget']], $minuteOptions);
|
$builder->add('minute', self::$widgets[$options['widget']], $minuteOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($options['with_seconds']) {
|
if ($options['with_seconds']) {
|
||||||
|
if (isset($emptyData['second'])) {
|
||||||
|
$secondOptions['empty_data'] = $emptyData['second'];
|
||||||
|
}
|
||||||
$builder->add('second', self::$widgets[$options['widget']], $secondOptions);
|
$builder->add('second', self::$widgets[$options['widget']], $secondOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -255,6 +269,9 @@ class TimeType extends AbstractType
|
|||||||
// representation is not \DateTime, but an array, we need to unset
|
// representation is not \DateTime, but an array, we need to unset
|
||||||
// this option.
|
// this option.
|
||||||
'data_class' => null,
|
'data_class' => null,
|
||||||
|
'empty_data' => function (Options $options) {
|
||||||
|
return $options['compound'] ? array() : '';
|
||||||
|
},
|
||||||
'compound' => $compound,
|
'compound' => $compound,
|
||||||
'choice_translation_domain' => false,
|
'choice_translation_domain' => false,
|
||||||
));
|
));
|
||||||
|
@ -31,16 +31,18 @@ use Symfony\Component\PropertyAccess\PropertyPath;
|
|||||||
*
|
*
|
||||||
* (1) the "model" format required by the form's object
|
* (1) the "model" format required by the form's object
|
||||||
* (2) the "normalized" format for internal processing
|
* (2) the "normalized" format for internal processing
|
||||||
* (3) the "view" format used for display
|
* (3) the "view" format used for display simple fields
|
||||||
|
* or map children model data for compound fields
|
||||||
*
|
*
|
||||||
* A date field, for example, may store a date as "Y-m-d" string (1) in the
|
* A date field, for example, may store a date as "Y-m-d" string (1) in the
|
||||||
* object. To facilitate processing in the field, this value is normalized
|
* object. To facilitate processing in the field, this value is normalized
|
||||||
* to a DateTime object (2). In the HTML representation of your form, a
|
* to a DateTime object (2). In the HTML representation of your form, a
|
||||||
* localized string (3) is presented to and modified by the user.
|
* localized string (3) may be presented to and modified by the user, or it could be an array of values
|
||||||
|
* to be mapped to choices fields.
|
||||||
*
|
*
|
||||||
* In most cases, format (1) and format (2) will be the same. For example,
|
* In most cases, format (1) and format (2) will be the same. For example,
|
||||||
* a checkbox field uses a Boolean value for both internal processing and
|
* a checkbox field uses a Boolean value for both internal processing and
|
||||||
* storage in the object. In these cases you simply need to set a value
|
* storage in the object. In these cases you simply need to set a view
|
||||||
* transformer to convert between formats (2) and (3). You can do this by
|
* transformer to convert between formats (2) and (3). You can do this by
|
||||||
* calling addViewTransformer().
|
* calling addViewTransformer().
|
||||||
*
|
*
|
||||||
@ -48,7 +50,7 @@ use Symfony\Component\PropertyAccess\PropertyPath;
|
|||||||
* demonstrate this, let's extend our above date field to store the value
|
* demonstrate this, let's extend our above date field to store the value
|
||||||
* either as "Y-m-d" string or as timestamp. Internally we still want to
|
* either as "Y-m-d" string or as timestamp. Internally we still want to
|
||||||
* use a DateTime object for processing. To convert the data from string/integer
|
* use a DateTime object for processing. To convert the data from string/integer
|
||||||
* to DateTime you can set a normalization transformer by calling
|
* to DateTime you can set a model transformer by calling
|
||||||
* addModelTransformer(). The normalized data is then converted to the displayed
|
* addModelTransformer(). The normalized data is then converted to the displayed
|
||||||
* data as described before.
|
* data as described before.
|
||||||
*
|
*
|
||||||
@ -217,7 +219,7 @@ class Form implements \IteratorAggregate, FormInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (null === $this->getName() || '' === $this->getName()) {
|
if (null === $this->getName() || '' === $this->getName()) {
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$parent = $this->parent;
|
$parent = $this->parent;
|
||||||
@ -340,8 +342,8 @@ class Form implements \IteratorAggregate, FormInterface
|
|||||||
$modelData = $event->getData();
|
$modelData = $event->getData();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Treat data as strings unless a value transformer exists
|
// Treat data as strings unless a transformer exists
|
||||||
if (!$this->config->getViewTransformers() && !$this->config->getModelTransformers() && is_scalar($modelData)) {
|
if (is_scalar($modelData) && !$this->config->getViewTransformers() && !$this->config->getModelTransformers()) {
|
||||||
$modelData = (string) $modelData;
|
$modelData = (string) $modelData;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1016,7 +1018,7 @@ class Form implements \IteratorAggregate, FormInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Normalizes the value if a normalization transformer is set.
|
* Normalizes the value if a model transformer is set.
|
||||||
*
|
*
|
||||||
* @param mixed $value The value to transform
|
* @param mixed $value The value to transform
|
||||||
*
|
*
|
||||||
@ -1038,7 +1040,7 @@ class Form implements \IteratorAggregate, FormInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reverse transforms a value if a normalization transformer is set.
|
* Reverse transforms a value if a model transformer is set.
|
||||||
*
|
*
|
||||||
* @param string $value The value to reverse transform
|
* @param string $value The value to reverse transform
|
||||||
*
|
*
|
||||||
@ -1062,7 +1064,7 @@ class Form implements \IteratorAggregate, FormInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transforms the value if a value transformer is set.
|
* Transforms the value if a view transformer is set.
|
||||||
*
|
*
|
||||||
* @param mixed $value The value to transform
|
* @param mixed $value The value to transform
|
||||||
*
|
*
|
||||||
@ -1093,7 +1095,7 @@ class Form implements \IteratorAggregate, FormInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reverse transforms a value if a value transformer is set.
|
* Reverse transforms a value if a view transformer is set.
|
||||||
*
|
*
|
||||||
* @param string $value The value to reverse transform
|
* @param string $value The value to reverse transform
|
||||||
*
|
*
|
||||||
|
@ -15,7 +15,7 @@ use Symfony\Component\Form\Exception\UnexpectedTypeException;
|
|||||||
use Symfony\Component\Form\Util\ServerParams;
|
use Symfony\Component\Form\Util\ServerParams;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A request handler using PHP's super globals $_GET, $_POST and $_SERVER.
|
* A request handler using PHP super globals $_GET, $_POST and $_SERVER.
|
||||||
*
|
*
|
||||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
*/
|
*/
|
||||||
@ -213,7 +213,7 @@ class NativeRequestHandler implements RequestHandlerInterface
|
|||||||
|
|
||||||
if (self::$fileKeys === $keys) {
|
if (self::$fileKeys === $keys) {
|
||||||
if (UPLOAD_ERR_NO_FILE === $data['error']) {
|
if (UPLOAD_ERR_NO_FILE === $data['error']) {
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
|
@ -596,4 +596,31 @@ class DateTimeTypeTest extends BaseTypeTest
|
|||||||
$this->assertSame($expectedData, $form->getNormData());
|
$this->assertSame($expectedData, $form->getNormData());
|
||||||
$this->assertSame($expectedData, $form->getData());
|
$this->assertSame($expectedData, $form->getData());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider provideEmptyData
|
||||||
|
*/
|
||||||
|
public function testSubmitNullUsesDateEmptyData($widget, $emptyData, $expectedData)
|
||||||
|
{
|
||||||
|
$form = $this->factory->create(static::TESTED_TYPE, null, array(
|
||||||
|
'widget' => $widget,
|
||||||
|
'empty_data' => $emptyData,
|
||||||
|
));
|
||||||
|
$form->submit(null);
|
||||||
|
|
||||||
|
$this->assertSame($emptyData, $form->getViewData());
|
||||||
|
$this->assertEquals($expectedData, $form->getNormData());
|
||||||
|
$this->assertEquals($expectedData, $form->getData());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function provideEmptyData()
|
||||||
|
{
|
||||||
|
$expectedData = \DateTime::createFromFormat('Y-m-d H:i', '2018-11-11 21:23');
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'Simple field' => array('single_text', '2018-11-11T21:23:00', $expectedData),
|
||||||
|
'Compound text field' => array('text', array('date' => array('year' => '2018', 'month' => '11', 'day' => '11'), 'time' => array('hour' => '21', 'minute' => '23')), $expectedData),
|
||||||
|
'Compound choice field' => array('choice', array('date' => array('year' => '2018', 'month' => '11', 'day' => '11'), 'time' => array('hour' => '21', 'minute' => '23')), $expectedData),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -983,25 +983,36 @@ class DateTypeTest extends BaseTypeTest
|
|||||||
));
|
));
|
||||||
$form->submit(null);
|
$form->submit(null);
|
||||||
|
|
||||||
// view transformer write back empty strings in the view data
|
// view transformer writes back empty strings in the view data
|
||||||
$this->assertSame(array('year' => '', 'month' => '', 'day' => ''), $form->getViewData());
|
$this->assertSame(array('year' => '', 'month' => '', 'day' => ''), $form->getViewData());
|
||||||
$this->assertSame($expectedData, $form->getNormData());
|
$this->assertSame($expectedData, $form->getNormData());
|
||||||
$this->assertSame($expectedData, $form->getData());
|
$this->assertSame($expectedData, $form->getData());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSingleTextSubmitNullUsesDefaultEmptyData()
|
/**
|
||||||
|
* @dataProvider provideEmptyData
|
||||||
|
*/
|
||||||
|
public function testSubmitNullUsesDateEmptyData($widget, $emptyData, $expectedData)
|
||||||
{
|
{
|
||||||
$emptyData = '2018-11-11';
|
|
||||||
$form = $this->factory->create(static::TESTED_TYPE, null, array(
|
$form = $this->factory->create(static::TESTED_TYPE, null, array(
|
||||||
'widget' => 'single_text',
|
'widget' => $widget,
|
||||||
'empty_data' => $emptyData,
|
'empty_data' => $emptyData,
|
||||||
));
|
));
|
||||||
$form->submit(null);
|
$form->submit(null);
|
||||||
|
|
||||||
$date = new \DateTime($emptyData);
|
|
||||||
|
|
||||||
$this->assertSame($emptyData, $form->getViewData());
|
$this->assertSame($emptyData, $form->getViewData());
|
||||||
$this->assertEquals($date, $form->getNormData());
|
$this->assertEquals($expectedData, $form->getNormData());
|
||||||
$this->assertEquals($date, $form->getData());
|
$this->assertEquals($expectedData, $form->getData());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function provideEmptyData()
|
||||||
|
{
|
||||||
|
$expectedData = \DateTime::createFromFormat('Y-m-d H:i:s', '2018-11-11 00:00:00');
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'Simple field' => array('single_text', '2018-11-11', $expectedData),
|
||||||
|
'Compound text fields' => array('text', array('year' => '2018', 'month' => '11', 'day' => '11'), $expectedData),
|
||||||
|
'Compound choice fields' => array('choice', array('year' => '2018', 'month' => '11', 'day' => '11'), $expectedData),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -776,9 +776,36 @@ class TimeTypeTest extends BaseTypeTest
|
|||||||
));
|
));
|
||||||
$form->submit(null);
|
$form->submit(null);
|
||||||
|
|
||||||
// view transformer write back empty strings in the view data
|
// view transformer writes back empty strings in the view data
|
||||||
$this->assertSame(array('hour' => '', 'minute' => ''), $form->getViewData());
|
$this->assertSame(array('hour' => '', 'minute' => ''), $form->getViewData());
|
||||||
$this->assertSame($expectedData, $form->getNormData());
|
$this->assertSame($expectedData, $form->getNormData());
|
||||||
$this->assertSame($expectedData, $form->getData());
|
$this->assertSame($expectedData, $form->getData());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider provideEmptyData
|
||||||
|
*/
|
||||||
|
public function testSubmitNullUsesDateEmptyData($widget, $emptyData, $expectedData)
|
||||||
|
{
|
||||||
|
$form = $this->factory->create(static::TESTED_TYPE, null, array(
|
||||||
|
'widget' => $widget,
|
||||||
|
'empty_data' => $emptyData,
|
||||||
|
));
|
||||||
|
$form->submit(null);
|
||||||
|
|
||||||
|
$this->assertSame($emptyData, $form->getViewData());
|
||||||
|
$this->assertEquals($expectedData, $form->getNormData());
|
||||||
|
$this->assertEquals($expectedData, $form->getData());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function provideEmptyData()
|
||||||
|
{
|
||||||
|
$expectedData = \DateTime::createFromFormat('Y-m-d H:i', '1970-01-01 21:23');
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'Simple field' => array('single_text', '21:23', $expectedData),
|
||||||
|
'Compound text field' => array('text', array('hour' => '21', 'minute' => '23'), $expectedData),
|
||||||
|
'Compound choice field' => array('choice', array('hour' => '21', 'minute' => '23'), $expectedData),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ class FormUtil
|
|||||||
* Returns whether the given data is empty.
|
* Returns whether the given data is empty.
|
||||||
*
|
*
|
||||||
* This logic is reused multiple times throughout the processing of
|
* This logic is reused multiple times throughout the processing of
|
||||||
* a form and needs to be consistent. PHP's keyword `empty` cannot
|
* a form and needs to be consistent. PHP keyword `empty` cannot
|
||||||
* be used as it also considers 0 and "0" to be empty.
|
* be used as it also considers 0 and "0" to be empty.
|
||||||
*
|
*
|
||||||
* @param mixed $data
|
* @param mixed $data
|
||||||
|
@ -128,7 +128,7 @@ class OrderedHashMap implements \ArrayAccess, \IteratorAggregate, \Countable
|
|||||||
$key = array() === $this->orderedKeys
|
$key = array() === $this->orderedKeys
|
||||||
// If the array is empty, use 0 as key
|
// If the array is empty, use 0 as key
|
||||||
? 0
|
? 0
|
||||||
// Imitate PHP's behavior of generating a key that equals
|
// Imitate PHP behavior of generating a key that equals
|
||||||
// the highest existing integer key + 1
|
// the highest existing integer key + 1
|
||||||
: 1 + (int) max($this->orderedKeys);
|
: 1 + (int) max($this->orderedKeys);
|
||||||
}
|
}
|
||||||
|
@ -56,8 +56,6 @@ class OrderedHashMapIterator implements \Iterator
|
|||||||
private $current;
|
private $current;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new iterator.
|
|
||||||
*
|
|
||||||
* @param array $elements The elements of the map, indexed by their
|
* @param array $elements The elements of the map, indexed by their
|
||||||
* keys
|
* keys
|
||||||
* @param array $orderedKeys The keys of the map in the order in which
|
* @param array $orderedKeys The keys of the map in the order in which
|
||||||
@ -84,7 +82,7 @@ class OrderedHashMapIterator implements \Iterator
|
|||||||
*/
|
*/
|
||||||
public function __destruct()
|
public function __destruct()
|
||||||
{
|
{
|
||||||
// Use array_splice() instead of isset() to prevent holes in the
|
// Use array_splice() instead of unset() to prevent holes in the
|
||||||
// array indices, which would break the initialization of $cursorId
|
// array indices, which would break the initialization of $cursorId
|
||||||
array_splice($this->managedCursors, $this->cursorId, 1);
|
array_splice($this->managedCursors, $this->cursorId, 1);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user