HEX
Server: Apache/2.4.52 (Ubuntu)
System: Linux aritmodecarnaval.es 5.15.0-79-generic #86-Ubuntu SMP Mon Jul 10 16:07:21 UTC 2023 x86_64
User: www-data (33)
PHP: 7.4.33
Disabled: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,
Upload Files
File: /home/www/aritmodecarnaval/comprar/Google/Spreadsheet/Sheet.php
<?php

/**
 * Google_Spreadsheet_Sheet
 * 
 * @class Fetch or process data in spreadsheet
 */

class Google_Spreadsheet_Sheet {

  private $client = null;
  private $id = null;
  private $name = null;
  private $sheet = null;
  private $values = null;

  public $header = null;
  public $items = null;

  private $options = array(
    'cache' => false,
    'cache_dir' => 'cache',
    'cache_expires' => 600
  );

  private $params = array(
    'valueInputOption' => 'USER_ENTERED'
  );

  /**
   * @constructor
   * @param string $name
   * @param string $id
   * @param Google_Client $client
   */
  public function __construct ($name, $id, $client) {
    $this->client = $client;
    $this->id = $id;
    $this->name = $name;
    $this->sheet = new Google_Service_Sheets($this->client);
  }

  /**
   * Configure options
   * 
   * @param array $options
   * @return $this
   */
  public function config ($options) {
    foreach ($options as $key => $value) {
      if (array_key_exists($key, $this->options)) {
        $this->options[$key] = $value;
      }
    }
    return $this;
  }

  /**
   * Initialize sheet with header items
   * 
   * @param array $header
   * @return Google_Service_Sheets_AppendValuesResponse $response
   */
  public function init ($header) {
    $this->fetch(true);
    if (!empty($this->values)) {
      throw new Exception("'{$this->name}' is not empty");
    }
    return $this->edit(1, 1, $header);
  }

  /**
   * Fetch data from Sheets API or cache
   * - Automatically parse the data
   * - When load data from remote, save cache
   * 
   * @param boolean $force
   * @return $this
   */
  public function fetch ($force = false) {
    if ($force || !$this->getCache(true)) {
      $res = $this->sheet->spreadsheets_values->get($this->id, $this->name);
      if ($res && is_object($res) && is_array($res->values)) {
        $this->values = $res->values;
        $this->parse();
        if ($this->options['cache']) {
          $this->saveCache();
        }
      }
    }
    else {
      $cache = $this->getCache();
      $this->values = $cache['values'];
      $this->parse();
    }
    return $this;
  }

  /**
   * Parse multidimensional array data from spreadsheet to associative array
   * 
   * @return $this
   */
  public function parse () {
    $values = $this->values;
    $header = array();
    $items = array();
    foreach ($values as $i => $row) {
      if (!$i) {
        $header = $row;
        continue;
      }
      $items[$i] = array();
      foreach ($header as $j => $key) {
        $items[$i][$key] = array_key_exists($j, $row) ? $row[$j] : '';
      }
    }
    $this->header = $header;
    $this->items = $items;
    return $this;
  }

  /**
   * Select row by condition
   * The condition has to be array or function
   * 
   * @param array|function $condition
   * @return array $result
   */
  public function select ($condition) {
    $result = null;
    if (is_callable($condition)) {
      $result = array_filter($this->items, $condition);
    }
    else if (is_array($condition)) {
      $result = array_filter($this->items, function ($row) use ($condition) {
        $valid = true;
        foreach ($condition as $key => $value) {
          if ($row[$key] !== $value) {
            $valid = false;
          }
        }
        return $valid;
      });
    }
    return $result;
  }

  /**
   * Update cells' value by row and column number
   * 
   * @param integer $row
   * @param integer $col
   * @param array|string $values
   * @return Google_Service_Sheets_AppendValuesResponse $response
   */
  public function edit ($row, $col, $values) {
    $values = gettype($values) !== 'array' ? (array) $values : $values;
    $target = $this->getColumnLetter($col) . $row;
    $range = implode('!', array($this->name, $target));
    $body = new Google_Service_Sheets_ValueRange(array('values' => array($values)));
    return $this->sheet->spreadsheets_values->update($this->id, $range, $body, $this->params);
  }

  /**
   * Insert a new row to spreadsheet
   * Forcely fetch up-to-date data from remote before inserting
   * 
   * @param array $vars
   * @return Google_Service_Sheets_AppendValuesResponse $response
   */
  public function insert ($vars) {
    $this->fetch(true);
    $vars = (array) $vars;
    $values = array();
    $values[] = array();
    foreach ($this->header as $key) {
      array_push($values[0], in_array($key, array_keys($vars)) ? (string) $vars[$key] : '');
    }
    $body = new Google_Service_Sheets_ValueRange(array('values' => $values));
    return $this->sheet->spreadsheets_values->append($this->id, $this->name, $body, $this->params);
  }

  /**
   * Update values by condition
   * Forcely fetch up-to-date data from remote before updating
   * 
   * @param array $vars
   * @param array|function $condition
   * @return Google_Service_Sheets_AppendValuesResponse $response
   */
  public function update ($vars, $condition) {
    $this->fetch(true);
    $rows = array_keys($this->select($condition));
    $data = array();
    foreach ($vars as $key => $value) {
      $c = array_search($key, $this->header);
      if (false === $c) continue;
      $col = $this->getColumnLetter($c + 1);
      foreach ($rows as $r) {
        $r += 1;
        $data[] = new Google_Service_Sheets_ValueRange(array(
          'range' => $this->name . "!${col}${r}",
          'values' => array(
            array($value)
          )
        ));
      }
    }
    if (count($data)) {
      $params = $this->params;
      $params['data'] = $data;
      $body = new Google_Service_Sheets_BatchUpdateValuesRequest($params);
      return $this->sheet->spreadsheets_values->batchUpdate($this->id, $body);
    }
    return null;
  }

  /**
   * Get column letter (A1 notation) from number
   * 
   * @param integer $index
   * @return string $result
   */
  private function getColumnLetter ($index) {
    $s = array();
    for ($i = $index; $i > 0; $i = intval(($i) / 26)) {
      array_push($s, chr(65 + (($i - 1) % 26)));
    }
    return implode('', array_reverse($s));
  }

  /**
   * Get cache file path
   * 
   * @return string $path
   */
  private function getCachePath () {
    return implode('/', array(
      $this->options['cache_dir'],
      $this->id,
      urlencode($this->name)
    ));
  }

  /**
   * Get cache data
   * Or test whether cache file exists and is alive
   * 
   * @param boolean $test
   * @return array|boolean $result
   */
  private function getCache ($test = false) {
    $file = $this->getCachePath();
    $hasCache = $this->options['cache']
      && file_exists($file)
      && (time() - filemtime($file)) < $this->options['cache_expires'];
    if ($test) {
      return $hasCache;
    } elseif ($hasCache) {
      return unserialize(file_get_contents($file));
    }
    return null;
  }

  /**
   * Save current data to cache file
   */
  private function saveCache () {
    $dir = implode('/', array($this->options['cache_dir'], $this->id));
    if (!file_exists($dir)) {
      mkdir($dir);
    }
    return file_put_contents($this->getCachePath(), serialize(array(
      'values' => $this->values
    )));
  }

}