19 declare(strict_types=1);
    46         [
'field_id' => 1, 
'lang_code' => 
'de', 
'idx' => 0, 
'value' => 
'1val0de', 
'position' => 1],
    47         [
'field_id' => 1, 
'lang_code' => 
'en', 
'idx' => 0, 
'value' => 
'1val0en', 
'position' => 1],
    48         [
'field_id' => 1, 
'lang_code' => 
'de', 
'idx' => 1, 
'value' => 
'1val1de', 
'position' => 0],
    49         [
'field_id' => 1, 
'lang_code' => 
'en', 
'idx' => 1, 
'value' => 
'1val1en', 
'position' => 0],
    50         [
'field_id' => 1, 
'lang_code' => 
'de', 
'idx' => 2, 
'value' => 
'1val2de', 
'position' => 2],
    51         [
'field_id' => 1, 
'lang_code' => 
'en', 
'idx' => 2, 
'value' => 
'1val2en', 
'position' => 2],
    52         [
'field_id' => 2, 
'lang_code' => 
'de', 
'idx' => 0, 
'value' => 
'2val0de', 
'position' => 1],
    53         [
'field_id' => 2, 
'lang_code' => 
'en', 
'idx' => 0, 
'value' => 
'2val0en', 
'position' => 1],
    54         [
'field_id' => 2, 
'lang_code' => 
'de', 
'idx' => 1, 
'value' => 
'2val1de', 
'position' => 0],
    55         [
'field_id' => 2, 
'lang_code' => 
'en', 
'idx' => 1, 
'value' => 
'2val1en', 
'position' => 0],
    56         [
'field_id' => 2, 
'lang_code' => 
'de', 
'idx' => 2, 
'value' => 
'2val2de', 
'position' => 2],
    57         [
'field_id' => 2, 
'lang_code' => 
'en', 
'idx' => 2, 
'value' => 
'2val2en', 
'position' => 2]
    62         foreach ($a as $key => $item) {
    63             if (isset($item[
'status'])) {
    64                 unset($a[$key][
'status']);
    67         foreach ($b as $key => $item) {
    68             if (isset($item[
'status'])) {
    69                 unset($b[$key][
'status']);
    73         if (count($a) !== count($b)) {
    77         foreach ($a as $item) {
    78             if (!in_array($item, $b)) {
    93             public function exposeData(): array
    98             protected function deleteOptionsExcept(
int $field_id, 
int ...$keep_option_ids): 
void   100                 foreach ($this->data as $key => $datum) {
   101                     if ($datum[
'field_id'] !== $field_id) {
   104                     if (!in_array($datum[
'idx'], $keep_option_ids)) {
   105                         unset($this->data[$key]);
   110             protected function deleteTranslationsOfOptionExcept(
   113                 string ...$keep_languages
   115                 foreach ($this->data as $key => $datum) {
   116                     if ($datum[
'idx'] !== $option_id || $datum[
'field_id'] !== $field_id) {
   119                     if (!in_array($datum[
'lang_code'], $keep_languages)) {
   120                         unset($this->data[$key]);
   125             protected function createTranslation(
   129                 OptionTranslation $translation
   132                     'field_id' => $field_id,
   133                     'lang_code' => $translation->language(),
   135                     'value' => $translation->getValue(),
   136                     'position' => $position
   140             protected function updateTranslation(
   144                 OptionTranslation $translation
   146                 foreach ($this->data as $key => $datum) {
   148                         $datum[
'idx'] !== $option_id ||
   149                         $datum[
'field_id'] !== $field_id ||
   150                         $datum[
'lang_code'] !== $translation->language()
   154                     $this->data[$key][
'value'] = $translation->getValue();
   155                     $this->data[$key][
'position'] = $position;
   159             protected function getNextOptionIDInField(
int $field_id): 
int   162                 foreach ($this->data as $datum) {
   163                     if ($datum[
'field_id'] !== $field_id) {
   166                     $max_id = max($max_id, $datum[
'idx']);
   176         bool $contains_changes,
   178     ): SelectSpecificData {
   179         $rows_by_option_id = [];
   180         foreach ($rows as $row) {
   181             if ($row[
'field_id'] !== $field_id) {
   184             $rows_by_option_id[$row[
'idx']][] = $row;
   188         foreach ($rows_by_option_id as $rows) {
   192         $field_id = $is_persisted ? $field_id : null;
   194         return new class ($field_id, $contains_changes, $options) extends NullSelectSpecificData {
   196                 protected ?
int $field_id,
   197                 protected bool $contains_changes,
   198                 protected array $options
   202             public function isPersisted(): 
bool   204                 return !is_null($this->field_id);
   207             public function containsChanges(): 
bool   209                 return $this->contains_changes;
   212             public function fieldID(): ?
int   214                 return $this->field_id;
   217             public function getOptions(): \Generator
   219                 yield 
from $this->options;
   226         $first_row = $rows[0];
   227         $option_id = in_array(self::OPTION_NOT_PERSISTED, $first_row[
'status'] ?? []) ?
   230         $position = $first_row[
'position'];
   231         $contains_changes = in_array(self::OPTION_CHANGED, $first_row[
'status'] ?? []);
   234         foreach ($rows as $row) {
   238         return new class ($option_id, $position, $contains_changes, $translations) extends NullOption {
   240                 protected ?
int $option_id,
   241                 protected int $position,
   242                 protected bool $contains_changes,
   243                 protected array $translations
   247             public function isPersisted(): 
bool   249                 return !is_null($this->option_id);
   252             public function containsChanges(): 
bool   254                 return $this->contains_changes;
   257             public function optionID(): ?
int   259                 return $this->option_id;
   262             public function getPosition(): 
int   264                 return $this->position;
   267             public function getTranslations(): \Generator
   269                 yield 
from $this->translations;
   276         $language = $row[
'lang_code'];
   277         $value = $row[
'value'];
   278         $is_persisted = !in_array(self::TRANSLATION_NOT_PERSISTED, $row[
'status'] ?? []);
   279         $contains_changes = in_array(self::TRANSLATION_CHANGED, $row[
'status'] ?? []);
   281         return new class ($language, $value, $is_persisted, $contains_changes) extends NullOptionTranslation {
   283                 protected string $language,
   284                 protected string $value,
   285                 protected bool $is_persisted,
   286                 protected bool $contains_changes
   290             public function isPersisted(): 
bool   292                 return $this->is_persisted;
   295             public function containsChanges(): 
bool   297                 return $this->contains_changes;
   302                 return $this->language;
   316             self::OPTION_CHANGED,
   317             self::OPTION_NOT_PERSISTED,
   318             self::TRANSLATION_CHANGED,
   319             self::TRANSLATION_NOT_PERSISTED
   321         $added_data_array = [
   322             [
'field_id' => 78, 
'lang_code' => 
'de', 
'idx' => 1, 
'value' => 
'3val0de', 
'position' => 1, 
'status' => $status],
   323             [
'field_id' => 78, 
'lang_code' => 
'en', 
'idx' => 1, 
'value' => 
'3val0en', 
'position' => 1, 
'status' => $status],
   324             [
'field_id' => 78, 
'lang_code' => 
'de', 
'idx' => 2, 
'value' => 
'3val1de', 
'position' => 0, 
'status' => $status]
   326         $new_data_array = array_merge(self::ORIGINAL_DATA, $added_data_array);
   334         $gateway->create(78, $new_data);
   337             $gateway->exposeData()
   344         $new_data_array = self::ORIGINAL_DATA;
   345         foreach ($new_data_array as $key => $item) {
   346             if ($item[
'field_id'] === 1 && $item[
'idx'] === 0) {
   347                 unset($new_data_array[$key]);
   357         $gateway->update($new_data);
   360             $gateway->exposeData()
   368             self::OPTION_CHANGED,
   369             self::OPTION_NOT_PERSISTED,
   370             self::TRANSLATION_CHANGED,
   371             self::TRANSLATION_NOT_PERSISTED
   373         $added_data_array = [
   374             [
'field_id' => 1, 
'lang_code' => 
'de', 
'idx' => 3, 
'value' => 
'1val3de', 
'position' => 3, 
'status' => $status],
   375             [
'field_id' => 1, 
'lang_code' => 
'en', 
'idx' => 3, 
'value' => 
'1val3en', 
'position' => 3, 
'status' => $status]
   377         $new_data_array = array_merge(self::ORIGINAL_DATA, $added_data_array);
   385         $gateway->update($new_data);
   388             $gateway->exposeData()
   395         $new_data_array = self::ORIGINAL_DATA;
   396         $status = [self::OPTION_CHANGED];
   397         $new_data_array[0][
'position'] = 54;
   398         $new_data_array[0][
'status'] = $status;
   399         $new_data_array[1][
'position'] = 54;
   400         $new_data_array[1][
'status'] = $status;
   408         $gateway->update($new_data);
   411             $gateway->exposeData()
   418         $new_data_array = self::ORIGINAL_DATA;
   419         $status = [self::OPTION_CHANGED];
   420         foreach ($new_data_array as $key => $item) {
   421             if ($item[
'field_id'] !== 1 || $item[
'idx'] !== 0) {
   424             if ($item[
'lang_code'] === 
'en') {
   425                 unset($new_data_array[$key]);
   428             $new_data_array[$key][
'status'] = $status;
   437         $gateway->update($new_data);
   440             $gateway->exposeData()
   448             self::OPTION_CHANGED,
   449             self::TRANSLATION_CHANGED,
   450             self::TRANSLATION_NOT_PERSISTED
   452         $new_data_array = self::ORIGINAL_DATA;
   453         foreach ($new_data_array as $key => $item) {
   454             if ($item[
'field_id'] === 1 || $item[
'idx'] === 1) {
   455                 $new_data_array[$key][
'status'] = [self::OPTION_CHANGED];
   459             [
'field_id' => 1, 
'lang_code' => 
'fr', 
'idx' => 1, 
'value' => 
'1val1fr', 
'position' => 0, 
'status' => $status];
   467         $gateway->update($new_data);
   470             $gateway->exposeData()
   477         $new_data_array = self::ORIGINAL_DATA;
   478         foreach ($new_data_array as $key => $item) {
   479             if ($item[
'field_id'] === 2 || $item[
'idx'] === 1) {
   480                 $new_data_array[$key][
'status'] = [self::OPTION_CHANGED];
   483         $new_data_array[4][
'value'] = 
'different value';
   484         $new_data_array[4][
'status'] = [self::OPTION_CHANGED, self::TRANSLATION_CHANGED];
   492         $gateway->update($new_data);
   495             $gateway->exposeData()
 
__construct()
Constructor setup ILIAS global object  public. 
 
$a
thx to https://mlocati.github.io/php-cs-fixer-configurator for the examples 
 
language()
 description: > Example for rendring a language glyph.