Skip to content
This repository has been archived by the owner on Jan 10, 2023. It is now read-only.

Commit

Permalink
Fix for files props number 2
Browse files Browse the repository at this point in the history
  • Loading branch information
arrilot committed Feb 21, 2019
1 parent f6ee048 commit e47441f
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 64 deletions.
77 changes: 54 additions & 23 deletions src/Models/ElementModel.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,13 @@ class ElementModel extends BitrixModel
*/
protected static $objectClass = 'CIBlockElement';

/**
* Iblock PropertiesData from Bitrix DB
*
* @var null|array
*/
protected static $iblockPropertiesData = [];

/**
* Have sections been already fetched from DB?
*
Expand Down Expand Up @@ -141,6 +148,38 @@ public static function internalDirectCreate($bxObject, $fields)
return $bxObject->add($fields, static::$workFlow, static::$updateSearch, static::$resizePictures);
}

/**
* Fetches static::$iblockPropertiesData if it's not fetched and returns it.
*
* @return array
*/
protected static function getCachedIblockPropertiesData()
{
$iblockId = static::iblockId();
if (!empty(self::$iblockPropertiesData[$iblockId])) {
return self::$iblockPropertiesData[$iblockId];
}

$props = [];
$dbRes = CIBlock::GetProperties($iblockId, [], []);
while($property = $dbRes->Fetch()) {
$props[$property['CODE']] = $property;
}

return self::$iblockPropertiesData[$iblockId] = $props;
}

/**
* Setter for self::$iblockPropertiesData[static::iblockId()] mainly for testing.
*
* @param $data
* @return void
*/
public static function setCachedIblockPropertiesData($data)
{
self::$iblockPropertiesData[static::iblockId()] = $data;
}

/**
* Corresponding section model full qualified class name.
* MUST be overridden if you are going to use section model for this iblock.
Expand Down Expand Up @@ -420,6 +459,8 @@ protected function constructPropertyValuesForSave($selectedFields = [])
$propertyValues = [];
$saveOnlySelected = !empty($selectedFields);

$iblockPropertiesData = static::getCachedIblockPropertiesData();

if ($saveOnlySelected) {
foreach ($selectedFields as $code) {
// if we pass PROPERTY_X_DESCRIPTION as selected field, we need to add PROPERTY_X_VALUE as well.
Expand Down Expand Up @@ -449,36 +490,37 @@ protected function constructPropertyValuesForSave($selectedFields = [])

if (preg_match('/^PROPERTY_(.*)_VALUE$/', $code, $matches) && !empty($matches[1])) {
$propertyCode = $matches[1];

$iblockPropertyData = (array) $iblockPropertiesData[$propertyCode];

// if file was not changed skip it or it will be duplicated
if ($iblockPropertyData && $iblockPropertyData['PROPERTY_TYPE'] === 'F' && !empty($this->original[$code]) && $this->original[$code] === $value) {
continue;
}

// if property type is a list we need to use enum ID/IDs as value/values
if (array_key_exists("PROPERTY_{$propertyCode}_ENUM_ID", $this->fields)) {
$value = $this->fields["PROPERTY_{$propertyCode}_ENUM_ID"];
} else {
// if we suspect multiple list and PROPERTY_{$propertyCode}_ENUM_ID is not explicitly set.
if (is_array($value) && (count($value) == 0 || array_keys($value)[0] != 0)) {
$propertyData = CIBlock::GetProperties(static::iblockId(), [], ["CODE" => $propertyCode, "PROPERTY_TYPE" => "L", "MULTIPLE" => "Y"])->Fetch();
if ($propertyData) {
$value = array_keys($value);
}
}
} elseif ($iblockPropertyData && $iblockPropertyData['PROPERTY_TYPE'] === 'L' && $iblockPropertyData['MULTIPLE'] === 'Y') {
$value = array_keys($value);
}

// if property values have descriptions
if (array_key_exists("PROPERTY_{$propertyCode}_DESCRIPTION", $this->fields)) {
// we skip file properties here for now because they cause endless problems. Handle them manually.
if (array_key_exists("PROPERTY_{$propertyCode}_DESCRIPTION", $this->fields) && (!$iblockPropertyData || $iblockPropertyData['PROPERTY_TYPE'] !== 'F')) {
$description = $this->fields["PROPERTY_{$propertyCode}_DESCRIPTION"];

if (is_array($value) && is_array($description)) {
// for multiple property
foreach ($value as $rowIndex => $rowValue) {
$propertyValues[$propertyCode][] = [
'VALUE' => $this->preventValueNesting($rowValue),
'VALUE' => $rowValue,
'DESCRIPTION' => $description[$rowIndex]
];
}
} else {
// for single property
$propertyValues[$propertyCode] = [
'VALUE' => $this->preventValueNesting($value),
'VALUE' => $value,
'DESCRIPTION' => $description
];
}
Expand Down Expand Up @@ -572,15 +614,4 @@ public static function setResizePictures($value)
{
static::$resizePictures = $value;
}

/**
* For some cases (for saving example props with file type) we get ['VALUE' => ['VALUE' => [...]]] that breaks everything.
*
* @param mixed $value
* @return mixed
*/
protected function preventValueNesting($value)
{
return is_array($value) && array_key_exists('VALUE', $value) ? $value['VALUE'] : $value;
}
}
81 changes: 40 additions & 41 deletions tests/ElementModelTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Arrilot\Tests\BitrixModels;

use Arrilot\BitrixModels\Models\ElementModel;
use Arrilot\BitrixModels\Queries\ElementQuery;
use Arrilot\Tests\BitrixModels\Stubs\TestElement;
use Arrilot\Tests\BitrixModels\Stubs\TestSection;
Expand Down Expand Up @@ -70,6 +71,11 @@ public function testActivate()
$bxObject->shouldReceive('update')->with(1, ['ACTIVE' => 'Y'], false, true, false)->once()->andReturn(true);

TestElement::$bxObject = $bxObject;
TestElement::setCachedIblockPropertiesData([
'FOO' => [],
'TEST_LIST' => [],
'FOO2' => [],
]);
$element = new TestElement(1);

$this->assertTrue($element->activate());
Expand All @@ -81,6 +87,11 @@ public function testDeactivate()
$bxObject->shouldReceive('update')->with(1, ['ACTIVE' => 'N'], false, true, false)->once()->andReturn(true);

TestElement::$bxObject = $bxObject;
TestElement::setCachedIblockPropertiesData([
'FOO' => [],
'TEST_LIST' => [],
'FOO2' => [],
]);
$element = new TestElement(1);

$this->assertTrue($element->deactivate());
Expand Down Expand Up @@ -242,6 +253,23 @@ public function testSave()
$bxObject = m::mock('obj');

TestElement::$bxObject = $bxObject;
TestElement::setCachedIblockPropertiesData([
'FOO' => [
"ID" => "71",
"PROPERTY_TYPE" => "S",
"MULTIPLE" => "N",
],
'TEST_LIST' => [
"ID" => "72",
"PROPERTY_TYPE" => "L",
"MULTIPLE" => "N",
],
'TEST_LIST_MULTIPLE' => [
"ID" => "73",
"PROPERTY_TYPE" => "L",
"MULTIPLE" => "Y",
],
]);
$element = m::mock('Arrilot\Tests\BitrixModels\Stubs\TestElement[get,onBeforeSave,onAfterSave,onBeforeUpdate,onAfterUpdate]', [1])
->shouldAllowMockingProtectedMethods();

Expand All @@ -263,26 +291,9 @@ public function testSave()
'PROPERTY_TEST_LIST_ENUM_ID' => '1',
'PROPERTY_TEST_LIST_VALUE' => 'Test value of list',
'PROPERTY_TEST_LIST_VALUE_ID' => '28:72',
'PROPERTY_FOO2_VALUE'=> [
'VALUE' => [
'name' => '',
'type' => '',
'tmp_name' => '',
'size' => 0,
'del' => 'Y',
],
],
'~PROPERTY_FOO2_VALUE' => [
'VALUE' => [
'name' => '',
'type' => '',
'tmp_name' => '',
'size' => 0,
'del' => 'Y',
],
],
'PROPERTY_FOO2_DESCRIPTION' => 'baz2',
'~PROPERTY_FOO2_DESCRIPTION' => '~baz2',
'PROPERTY_TEST_LIST_MULTIPLE_VALUE' => [19 => "5", 18 => "4"],
'PROPERTY_TEST_LIST_MULTIPLE_DESCRIPTION' => [null, null],
'PROPERTY_TEST_LIST_MULTIPLE_PROPERTY_VALUE_ID' => ['648', '649'],
];
$element->shouldReceive('get')->andReturn($fields);
$element->fill($fields);
Expand All @@ -295,17 +306,11 @@ public function testSave()
$bxObject->shouldReceive('setPropertyValues')
->with(1, TestElement::iblockId(), [
'FOO' => ['VALUE' => 'bar', 'DESCRIPTION' => 'baz'],
'FOO2'=> [
'VALUE' => [
'name' => '',
'type' => '',
'tmp_name' => '',
'size' => 0,
'del' => 'Y',
],
'DESCRIPTION' => 'baz2'
],
'TEST_LIST' => '1',
'TEST_LIST_MULTIPLE'=> [
['VALUE' => 19, 'DESCRIPTION' => null],
['VALUE' => 18, 'DESCRIPTION' => null],
],
])
->once()
->andReturn(true);
Expand All @@ -323,20 +328,14 @@ public function testSave()
// 4
$bxObject->shouldReceive('setPropertyValuesEx')
->with(1, TestElement::iblockId(), [
'FOO2' => [
'VALUE' => [
'name' => '',
'type' => '',
'tmp_name' => '',
'size' => 0,
'del' => 'Y',
],
'DESCRIPTION' => 'baz2'
]
'TEST_LIST_MULTIPLE' => [
['VALUE' => 19, 'DESCRIPTION' => null],
['VALUE' => 18, 'DESCRIPTION' => null],
],
])
->once()
->andReturn(true);
$this->assertTrue($element->save(['PROPERTY_FOO2_VALUE']));
$this->assertTrue($element->save(['PROPERTY_TEST_LIST_MULTIPLE_VALUE']));

// 5
$bxObject->shouldReceive('setPropertyValuesEx')
Expand Down

0 comments on commit e47441f

Please sign in to comment.