items = $items; $this->watermark = $watermark; $this->version = $version ?? self::FORMAT_VERSION_V1; } public static function hydrate( array $record ): self { $variables = []; foreach ( $record['data'] ?? [] as $id => $item ) { $data = array_merge( [ 'id' => $id ], $item ); $variables[ $id ] = Variable::from_array( $data ); } $watermark = $record['watermark']; $version = $record['version'] ?? null; return new self( $variables, $watermark, $version ); } public function serialize( bool $include_deleted_key = false ): array { $data = []; foreach ( $this->all() as $variable ) { $var = $variable->to_array(); if ( $include_deleted_key && $variable->is_deleted() ) { $var['deleted'] = true; } $data[ $variable->id() ] = $var; } return [ 'data' => $data, 'watermark' => $this->watermark, 'version' => $this->version, ]; } public function set_version( $version ): void { $this->version = $version; } public static function default(): self { return new self( [], 0, self::FORMAT_VERSION_V1 ); } public function watermark(): int { return $this->watermark; } private function reset_watermark() { $this->watermark = 0; } public function increment_watermark() { if ( PHP_INT_MAX === $this->watermark ) { $this->reset_watermark(); } ++$this->watermark; } public function add_variable( Variable $variable ): void { $this->items[ $variable->id() ] = $variable; } /** * @throws RecordNotFound When a variable is not found. */ public function find_or_fail( string $id ): Variable { $variable = $this->get( $id ); if ( ! isset( $variable ) ) { throw new RecordNotFound( 'Variable not found' ); } return $variable; } /** * @throws DuplicatedLabel If there is a duplicate label in the database. */ public function assert_label_is_unique( string $label, ?string $ignore_id = null ): void { foreach ( $this->all() as $variable ) { if ( $variable->is_deleted() ) { continue; } if ( null !== $ignore_id && $variable->id() === $ignore_id ) { continue; } if ( strcasecmp( $variable->label(), $label ) === 0 ) { throw new DuplicatedLabel( esc_html( "Variable label '$label' already exists." ) ); } } } /** * @throws VariablesLimitReached If variable limit reached. */ public function assert_limit_not_reached(): void { $active_count = 0; foreach ( $this->all() as $variable ) { if ( ! $variable->is_deleted() ) { ++$active_count; } } if ( self::TOTAL_VARIABLES_COUNT <= $active_count ) { throw new VariablesLimitReached( 'Total variables count limit reached' ); } } public function next_id(): string { return Utils::generate_id( 'e-gv-', array_keys( $this->all() ) ); } public function get_next_order(): int { $highest_order = 0; foreach ( $this->all() as $variable ) { if ( $variable->is_deleted() ) { continue; } if ( $variable->has_order() && $variable->order() > $highest_order ) { $highest_order = $variable->order(); } } return $highest_order + 1; } }