Subversion Repositories web.creative

Rev

Blame | Last modification | View Log | Download

<?php namespace ProcessWire;

/**
 * ProcessWire Image Fieldtype
 *
 * Field that stores one or more image files. 
 *
 * For documentation about the fields used in this class, please see:  
 * /wire/core/Fieldtype.php
 * /wire/core/FieldtypeMulti.php
 * 
 * ProcessWire 3.x, Copyright 2020 by Ryan Cramer
 * https://processwire.com
 *
 *
 */

class FieldtypeImage extends FieldtypeFile {
  
  /**
   * File schema is configured to store dimensions for image files 'width', 'height', 'ratio' (flag)
   *
   */
  const fileSchemaDimensions = 256;

  /**
   * Get module info
   * 
   * @return array
   * 
   */
  public static function getModuleInfo() {
    return array(
      'title' => 'Images',
      'version' => 102,
      'summary' => 'Field that stores one or more GIF, JPG, or PNG images',
      'permanent' => true, 
    );
  }

  /**
   * Get blank value
   * 
   * @param Page $page
   * @param Field $field
   * @return Pageimages|Pagefiles
   * 
   */
  public function getBlankValue(Page $page, Field $field) {
    $pageimages = $this->wire(new Pageimages($page));
    $pageimages->setField($field);
    $pageimages->setTrackChanges(true); 
    return $pageimages; 
  }

  /**
   * @param Pagefiles $pagefiles
   * @param string $filename
   * @return Pageimage|Pagefile
   * 
   */
  protected function getBlankPagefile(Pagefiles $pagefiles, $filename) {
    return $this->wire(new Pageimage($pagefiles, $filename)); 
  }

  /**
   * Get default file extensions 
   * @return string
   * 
   */
  protected function getDefaultFileExtensions() {
    return "gif jpg jpeg png";
  }
  
  /**
   * Check and update database schema according to current version and features
   *
   * @param Field $field
   * @param array $schema Updated directly
   * @param int $fileSchema The fileSchema version flags integer
   * @return int Updated fileSchema flags integer
   * @since 3.0.154
   *
   */
  protected function updateDatabaseSchema(Field $field, array &$schema, $fileSchema) {
    
    $fileSchema = parent::updateDatabaseSchema($field, $schema, $fileSchema); 

    $hasDimensions = $fileSchema & self::fileSchemaDimensions;
    
    $schema['width'] = 'int';
    $schema['height'] = 'int';
    $schema['ratio'] = 'decimal(4,2)';
    
    $schema['keys']['width'] = 'index (width)';
    $schema['keys']['height'] = 'index (height)';
    $schema['keys']['ratio'] = 'index (ratio)';
    
    if(!$hasDimensions) {
      $numErrors = 0;
      if($this->wire('database')->tableExists($field->getTable())) {
        $columns = array('width', 'height', 'ratio');
        foreach($columns as $column) {
          if(!$this->addColumn($field, $column, $schema)) $numErrors++;
          if($numErrors) break;
        }
      } else {
        // new field being created that is getting initial schema to create table
      }
      if(!$numErrors) {
        $fileSchema = $fileSchema | self::fileSchemaDimensions;
      }
    }
    
    return $fileSchema;
  }
  
  /**
   * Convert individual Pagefile to array for storage in DB
   *
   * @param Page $page
   * @param Field $field
   * @param Pagefile|Pageimage $pagefile
   * @return array
   *
   */
  protected function sleepFile(Page $page, Field $field, Pagefile $pagefile) {
    
    $item = parent::sleepFile($page, $field, $pagefile); 

    $fileSchema = (int) $field->get('fileSchema');

    if($fileSchema & self::fileSchemaDimensions) {
      $info = $pagefile->getImageInfo(true);
      
      if(strpos($info['width'], '%')) $info['width'] = (-1 * (int) rtrim($info['width'], '%'));
      if(strpos($info['height'], '%')) $info['height'] = (-1 * (int) rtrim($info['height'], '%'));
      
      $item['width'] = (int) $info['width'];
      $item['height'] = (int) $info['height'];
      $item['ratio'] = number_format($pagefile->ratio, 2, '.', '');
    }
    
    return $item;
  }


  /**
   * Wakeup individual file converting array of data to Pagefile and adding it to Pagefiles
   *
   * @param Page $page
   * @param Field $field
   * @param Pagefiles $pagefiles
   * @param array $a Data from DB
   * @return Pagefile
   *
   */
  protected function wakeupFile(Page $page, Field $field, Pagefiles $pagefiles, array $a) {
  
    /** @var Pageimage $pagefile */
    $pagefile = parent::wakeupFile($page, $field, $pagefiles, $a); 
    
    if(!empty($a['width'])) {
      // dimension info already present in DB: populate to Pageimage object
      /*
      if($a['width'] < 0) $a['width'] = abs($a['width']) . '%';
      if($a['height'] < 0) $a['height'] = abs($a['height']) . '%';
      $pagefile->setImageInfo(array('width' => $a['width'], 'height' => $a['height']));
      */
    } else if(self::autoUpdateOnWakeup && (((int) $field->get('fileSchema')) & self::fileSchemaDimensions) && $pagefile->width()) {
      // dimension info not yet in DB: detect and populate in DB
      list($width, $height, $ratio) = array($pagefile->width(), $pagefile->height(), $pagefile->ratio);
      if(strpos($width, '%')) $width = (-1 * (int) rtrim($width, '%'));
      if(strpos($height, '%')) $height = (-1 * (int) rtrim($height, '%'));
      $this->saveFileCols($page, $field, $pagefile, array(
        'width' => $width,
        'height' => $height,
        'ratio' => $ratio,
      ));
    }
    
    return $pagefile;
  }

  /**
   * Export a Pageimages value to a portable PHP array
   * 
   * @param Page $page
   * @param Field $field
   * @param array|float|int|null|object|string $value
   * @param array $options
   * @return array
   * 
   */
  public function ___exportValue(Page $page, Field $field, $value, array $options = array()) {
    /** @var Pageimages $pagefiles */
    $pagefiles = $value; 
    $value = parent::___exportValue($page, $field, $value, $options); 
    if(empty($options['system'])) {
      foreach($value as $k => $v) {
        $img = $pagefiles->get($v['name']);
        $value[$k]['width'] = $img->width();
        $value[$k]['height'] = $img->height();
      }
    }
    
    if(!empty($options['FieldtypeImage'])) {
      $o = $options['FieldtypeImage']; 
      if(!empty($o['variations'])) {
        // include URLs to image variations
        foreach($value as $k => $v) {
          if(empty($options['system'])) {
            $img = $pagefiles->get($v['name']);
          } else {
            $img = $pagefiles->get($k); 
          }
          $variations = array();
          foreach($img->getVariations() as $variation) {
            /** @var Pageimage $variation */
            $variations[$variation->name] = $variation->httpUrl();
          }
          $value[$k]['variations'] = $variations;
          
        }
      }
    }
    
    return $value;  
  }

  /**
   * Get Inputfields to configure fields using this Fieldtype
   * 
   * @param Field $field
   * @return InputfieldWrapper
   * 
   */
  public function ___getConfigInputfields(Field $field) {

    $inputfields = parent::___getConfigInputfields($field);
    $f = $inputfields->get('outputString'); 
    $f->attr('placeholder', "i.e. <img src='{url}' alt='{description}' />");
    $f->notes .= ", {width}, {height}";
    
    return $inputfields; 
  }

  /*
  public function getInputfield(Page $page, Field $field) {

    // even though we don't want this input field, call it anyway
    parent::getInputfield($page, $field); 

    $inputfield = $this->modules->get("InputfieldImage"); 
    $inputfield->class = $this->className();

    $this->setupHooks($page, $field, $inputfield);

    return $inputfield;
  }
  */


}