praiadeseselle/wire/modules/LanguageSupport/LanguagesPageFieldValue.php
2022-03-08 15:55:41 +01:00

307 lines
7.5 KiB
PHP

<?php namespace ProcessWire;
/**
* Serves as a multi-language value placeholder for field values that contain a value in more than one language.
*
* ProcessWire 3.x, Copyright 2019 by Ryan Cramer
* https://processwire.com
*
*/
class LanguagesPageFieldValue extends Wire implements LanguagesValueInterface, \IteratorAggregate {
/**
* Inherit default language value when blank
*
*/
const langBlankInheritDefault = 0;
/**
* Don't inherit any value when blank
*
*/
const langBlankInheritNone = 1;
/**
* Values per language indexed by language ID
*
*/
protected $data = array();
/**
* Cached ID of default language page
*
*/
protected $defaultLanguagePageID = 0;
/**
* @var LanguageSupport|null
*
*/
protected $languageSupport = null;
/**
* Reference to Field that this value is for
*
*/
protected $field;
/**
* Reference to Page that this value is for
*
* @var Page
*
*/
protected $page;
/**
* Construct the multi language value
*
* @param Page $page
* @param Field $field
* @param array|string $values
*
*/
public function __construct(Page $page, Field $field, $values = null) { // #98
$page->wire($this);
$this->setPage($page);
$this->setField($field);
$this->languageSupport = $this->wire('modules')->get('LanguageSupport');
$this->defaultLanguagePageID = $this->languageSupport->defaultLanguagePageID;
if(!is_array($values)) {
$values = array('data' => $values);
}
$this->importArray($values);
}
/**
* Import array of language values
*
* Indexes may be:
* - “data123” where 123 is language ID or “data” for default language
* - "en” language name (may be any language name)
* - “123” language ID
*
* One index style must be used, you may not combine multiple.
*
* #pw-internal
*
* @param array $values
*
*/
public function importArray(array $values) {
reset($values);
$testKey = key($values);
if($testKey === null) return;
if(strpos($testKey, 'data') !== 0) {
// array does not use "data123" indexes, so work with language ID or language name indexes
// and convert to "data123" indexes
$_values = array();
foreach($values as $key => $value) {
if(ctype_digit("$key")) $key = (int) $key;
$language = $this->wire('languages')->get($key);
if($language && $language->id) {
$dataKey = $language->isDefault() ? "data" : "data$language->id";
$_values[$dataKey] = $value;
}
}
if(count($_values)) $values = $_values;
}
if(array_key_exists('data', $values)) {
if(is_null($values['data'])) $values['data'] = '';
$this->data[$this->defaultLanguagePageID] = $values['data'];
}
foreach($this->languageSupport->otherLanguagePageIDs as $id) {
$key = 'data' . $id;
$value = empty($values[$key]) ? '' : $values[$key];
$this->data[$id] = $value;
}
}
/**
* Sets the value for a given language
*
* @param int|Language|string $languageID Language object, id, or name
* @param mixed $value
* @return $this
*
*/
public function setLanguageValue($languageID, $value) {
if(is_object($languageID) && $languageID instanceof Language) $languageID = $languageID->id;
if(is_string($languageID) && !ctype_digit("$languageID")) $languageID = $this->wire('languages')->get($languageID)->id;
$existingValue = isset($this->data[$languageID]) ? $this->data[$languageID] : '';
if($value instanceof LanguagesPageFieldValue) {
// to avoid potential recursion
$value = $value->getLanguageValue($languageID);
}
if($value !== $existingValue) {
$this->trackChange('data', $existingValue, $value);
$this->trackChange('data' . $languageID, $existingValue, $value);
}
$this->data[(int)$languageID] = $value;
return $this;
}
/**
* Grab language values from Inputfield and populate to this object
*
* @param Inputfield $inputfield
*
*/
public function setFromInputfield(Inputfield $inputfield) {
foreach($this->wire('languages') as $language) {
if($language->isDefault) {
$key = 'value';
} else {
$key = 'value' . $language->id;
}
$this->setLanguageValue($language->id, $inputfield->$key);
}
}
/**
* Populate language values from this object to given Inputfield
*
* @param Inputfield $inputfield
* @since 3.0.170
*
*/
public function setToInputfield(Inputfield $inputfield) {
foreach($this->wire()->languages as $language) {
$key = $language->isDefault ? "value" : "value$language->id";
$inputfield->set($key, $this->getLanguageValue($language->id));
}
}
/**
* Given a language, returns the value in that language
*
* @param Language|int|string Language object, id, or name
* @return int
*
*/
public function getLanguageValue($languageID) {
if(is_object($languageID) && $languageID instanceof Language) $languageID = $languageID->id;
if(is_string($languageID) && !ctype_digit("$languageID")) $languageID = $this->wire('languages')->get($languageID)->id;
$languageID = (int) $languageID;
return isset($this->data[$languageID]) ? $this->data[$languageID] : '';
}
/**
* Returns the value in the default language
*
*/
public function getDefaultValue() {
return $this->data[$this->defaultLanguagePageID];
}
/**
* Get non-empty value in this order: current lang, default lang, other lang, failValue
*
* @param string $failValue Value to use if we cannot find a non-empty value
* @return string
* @since 3.0.147
*
*/
public function getNonEmptyValue($failValue = '') {
$value = (string) $this;
if(strlen($value)) return $value;
$value = (string) $this->getDefaultValue();
if(strlen($value)) return $value;
foreach($this->wire('languages') as $language) {
$value = $this->getLanguageValue($language->id);
if(strlen($value)) break;
}
if(!strlen($value)) $value = $failValue;
return $value;
}
/**
* The string value is the value in the current user's language
*
*/
public function __toString() {
if($this->wire('hooks')->isHooked('LanguagesPageFieldValue::getStringValue()')) {
return $this->__call('getStringValue', array());
} else {
return $this->___getStringValue();
}
}
protected function ___getStringValue() {
$template = $this->page->template;
$language = $this->wire()->user->language;
$defaultValue = (string) $this->data[$this->defaultLanguagePageID];
if(!$language || !$language->id || $language->isDefault()) return $defaultValue;
if($template && $template->noLang) return $defaultValue;
$languageValue = (string) (empty($this->data[$language->id]) ? '' : $this->data[$language->id]);
if(!strlen($languageValue)) {
// value is blank
if($this->field) {
if($this->field->langBlankInherit == self::langBlankInheritDefault) {
// inherit value from default language
$languageValue = $defaultValue;
}
}
}
return $languageValue;
}
public function setField(Field $field) {
$this->field = $field;
}
public function setPage(Page $page) {
$this->page = $page;
}
public function getPage() {
return $this->page;
}
public function getField() {
return $this->field;
}
public function __debugInfo() {
$info = parent::__debugInfo();
foreach($this->wire('languages') as $language) {
$info[$language->name] = isset($this->data[$language->id]) ? $this->data[$language->id] : '';
}
return $info;
}
/**
* Allows iteration of the languages values
*
* Fulfills \IteratorAggregate interface.
*
* @return \ArrayObject
*
*/
public function getIterator() {
return new \ArrayObject($this->data);
}
}