Subversion Repositories web.creative

Rev

Blame | Last modification | View Log | Download

<?php namespace ProcessWire;

/**
 * ProcessWire Password Fieldtype
 *
 * Fieldtype for holding a hashed and salted password
 *
 * For documentation about the fields used in this class, please see:  
 * /wire/core/Fieldtype.php
 * 
 * ProcessWire 3.x, Copyright 2016 by Ryan Cramer
 * https://processwire.com
 *
 */

class FieldtypePassword extends Fieldtype {

  public static function getModuleInfo() {
    return array(
      'title' => 'Password',
      'version' => 101,
      'summary' => 'Field that stores a hashed and salted password',
      'permanent' => true, 
      );
  }

  /**
   * Initialize the Fieldtype
   *
   */
  public function init() {
    return parent::init();
  }

  /**
   * Return the associated Inputfield
   * 
   * @param Page $page
   * @param Field $field
   * @return InputfieldPassword
   *
   */
  public function getInputfield(Page $page, Field $field) {
    /** @var InputfieldPassword $inputfield */
    $inputfield = $this->modules->get('InputfieldPassword'); 
    $inputfield->class = $this->className();
    $inputfield->setPage($page); 
    return $inputfield; 
  }

  /**
   * Return all Fieldtypes derived from FieldtypeText, which we will consider compatible
   * 
   * @param Field $field
   * @return null|array
   *
   */
  public function ___getCompatibleFieldtypes(Field $field) {
    return null;
  }

  /**
   * Sanitize value for runtime
   * 
   * @param Page $page
   * @param Field $field
   * @param Password|string $value
   * @return Password
   *
   */
  public function sanitizeValue(Page $page, Field $field, $value) {

    if($value instanceof Password) {
      $item = $value; 

    } else { 
      $item = $page->__isset($field->name) ? $page->get($field->name) : $this->getBlankValue($page, $field); 
      $item->pass = trim($value); 
    }

    if($item->isChanged()) $page->trackChange($field->name); 

    return $item; 
  }

  /**
   * Get a blank password item object
   * 
   * @param Page $page
   * @param Field $field
   * @return Password
   *
   */
  public function getBlankValue(Page $page, Field $field) {
    $item = $this->wire(new Password()); 
    $item->setTrackChanges(true);
    return $item; 
  }

  /**
   * Given a raw value (value as stored in DB), return the value as it would appear in a Page object
   *
   * @param Page $page
   * @param Field $field
   * @param array $value
   * @return Password
   *
   */
  public function ___wakeupValue(Page $page, Field $field, $value) {
    $wakeValue = $this->getBlankValue($page, $field); 
    $wakeValue->salt = $value['salt']; // salt must be set first when blowfish
    $wakeValue->hash = $value['data'];
    $wakeValue->setTrackChanges(true); 
    return $wakeValue; 
  }

  /**
   * Given an 'awake' value, as set by wakeupValue, convert the value back to a basic type for storage in DB. 
   *              
   * @param Page $page
   * @param Field $field
   * @param string|int|array|object $value
   * @return string|int
   *
   */
  public function ___sleepValue(Page $page, Field $field, $value) {

    if(!$value instanceof Password) return $value; 

    $sleepValue = array(
      'salt' => $value->salt, 
      'data' => $value->hash, 
      );

    // salt not needed for blowfish since it is prepended to the hash already
    // if($value->isBlowfish()) $sleepValue['salt'] = '';

    return $sleepValue; 
  }


  /**
   * Return the database schema in specified format
   * 
   * @param Field $field
   * @return array
   *
   */
  public function getDatabaseSchema(Field $field) {
    $schema = parent::getDatabaseSchema($field); 
    $schema['data'] = 'char(40) NOT NULL';
    $schema['salt'] = 'char(32) NOT NULL';
    $engine = $this->wire('config')->dbEngine;
    $schema['xtra']['append'] = "ENGINE=$engine DEFAULT CHARSET=ascii";
    return $schema;
  }


  /**
   * Return the fields required to configure an instance of FieldtypePassword
   * 
   * @param Field $field
   * @return InputfieldWrapper
   *
   */
  public function ___getConfigInputfields(Field $field) {
    $inputfields = parent::___getConfigInputfields($field);
    return $inputfields; 
  }
}