1:   2:   3:   4:   5:   6:   7:   8:   9:  10:  11:  12:  13:  14:  15:  16:  17:  18:  19:  20:  21:  22:  23:  24:  25:  26:  27:  28:  29:  30:  31:  32:  33:  34:  35:  36:  37:  38:  39:  40:  41:  42:  43:  44:  45:  46:  47:  48:  49:  50:  51:  52:  53:  54:  55:  56:  57:  58:  59:  60:  61:  62:  63:  64:  65:  66:  67:  68:  69:  70:  71:  72:  73:  74:  75:  76:  77:  78:  79:  80:  81:  82:  83:  84:  85:  86:  87:  88:  89:  90:  91:  92:  93:  94:  95:  96:  97:  98:  99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 
<?php
namespace Omeka\Settings;

use Omeka\Service\Exception;

/**
 * Manage settings in a differentiated setting table.
 */
abstract class AbstractTargetSettings extends AbstractSettings
{
    /**
     * @var int
     */
    protected $targetId;

    /**
     * Get the target ID column name of the setting table.
     *
     * @return string
     */
    abstract public function getTargetIdColumnName();

    /**
     * Set the ID of the target entity.
     *
     * @param int $targetId
     */
    public function setTargetId($targetId)
    {
        if ($targetId !== $this->targetId) {
            $this->cache = null;
        }
        $this->targetId = $targetId;
    }

    /**
     * Set a setting
     *
     * Allows consumers to temporarily overwrite the target ID.
     *
     * @param string $id
     * @param mixed $value
     * @param int $targetId
     */
    public function set($id, $value, $targetId = null)
    {
        $originalTargetId = $this->targetId;
        if ($targetId) {
            $this->setTargetId($targetId);
        }
        parent::set($id, $value);
        $this->setTargetId($originalTargetId);
    }

    /**
     * Get a setting
     *
     * Allows consumers to temporarily overwrite the target ID.
     *
     * @param string $id
     * @param mixed $default
     * @param int $targetId
     * @return mixed
     */
    public function get($id, $default = null, $targetId = null)
    {
        $originalTargetId = $this->targetId;
        if ($targetId) {
            $this->setTargetId($targetId);
        }
        $setting = parent::get($id, $default);
        $this->setTargetId($originalTargetId);
        return $setting;
    }

    /**
     * Delete a setting
     *
     * Allows consumers to temporarily overwrite the target ID.
     *
     * @param string $id
     * @param int $targetId
     */
    public function delete($id, $targetId = null)
    {
        $originalTargetId = $this->targetId;
        if ($targetId) {
            $this->setTargetId($targetId);
        }
        parent::delete($id);
        $this->setTargetId($originalTargetId);
    }

    protected function setCache()
    {
        if (!$this->targetId) {
            throw new Exception\RuntimeException('Cannot manage settings when no target ID is set.');
        }
        $sql = sprintf('SELECT * FROM %s WHERE %s = ?', $this->getTableName(), $this->getTargetIdColumnName());
        $settings = $this->connection->fetchAll($sql, [$this->targetId]);
        foreach ($settings as $setting) {
            $this->cache[$setting['id']] = $this->connection->convertToPHPValue($setting['value'], 'json_array');
        }
    }

    protected function setSetting($id, $value)
    {
        if (!$this->targetId) {
            throw new Exception\RuntimeException('Cannot manage a settings when no target ID is set.');
        }
        $sql = sprintf('SELECT * FROM %s WHERE id = ? AND %s = ?', $this->getTableName(), $this->getTargetIdColumnName());
        $setting = $this->connection->fetchAssoc($sql, [$id, $this->targetId]);
        if ($setting) {
            $this->connection->update(
                $this->getTableName(),
                ['value' => $value],
                ['id' => $id, $this->getTargetIdColumnName() => $this->targetId],
                ['json_array']
            );
        } else {
            $this->connection->insert(
                $this->getTableName(),
                ['value' => $value, $this->getTargetIdColumnName() => $this->targetId, 'id' => $id],
                ['json_array', \PDO::PARAM_INT]
            );
        }
    }

    protected function deleteSetting($id)
    {
        if (!$this->targetId) {
            throw new Exception\RuntimeException('Cannot manage settings when no target ID is set.');
        }
        $this->connection->delete(
            $this->getTableName(),
            [$this->getTargetIdColumnName() => $this->targetId, 'id' => $id],
            [\PDO::PARAM_INT]
        );
    }
}