Subversion Repositories web.active

Rev

Rev 22 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download

<?php namespace ProcessWire;

/**
 * ProcessWire Module Fieldtype
 *
 * Field that stores reference to another Module. 
 *
 * 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 FieldtypeModule extends Fieldtype {

  public static function getModuleInfo() {
    return array(
      'title' => 'Module Reference',
      'version' => 101,
      'summary' => 'Field that stores a reference to another module',
      'permanent' => true, 
      );
  }

  public function getBlankValue(Page $page, Field $field) {
    $blankType = $field->get('blankType');
    if($blankType === 'zero') {
      $value = 0;
    } else if($blankType === 'false') {
      $value = false;
    } else if($blankType === 'placeholder') {
      $value = $this->wire(new ModulePlaceholder());
    } else {
      $value = null;
    }
    return $value;
  }

  public function isAdvanced() {
    return true; 
  }

  public function sanitizeValue(Page $page, Field $field, $value) {
    if(!$value) return $this->getBlankValue($page, $field);
    if($field->get('instantiateModule')) return $value instanceof Module ? $value : $this->modules->get($value); 
    if(ctype_digit("$value")) return $this->modules->getModuleClass((int) $value); 
    return $this->modules->getModuleID($value) ? $value : $this->getBlankValue($page, $field);
  }

  public function ___wakeupValue(Page $page, Field $field, $value) {
    if(empty($value)) return $this->getBlankValue($page, $field);
    if($field->get('instantiateModule')) return $this->wire('modules')->get($value); 
    return $this->wire('modules')->getModuleClass((int) $value); 
  }

  public function ___sleepValue(Page $page, Field $field, $value) {
    $blankValue = $this->getBlankValue($page, $field);
    if(!$value || "$blankValue" == "$value") {
      return 0;
    } else {
      return $this->modules->getModuleID($value);
    }
  }

  public function getInputfield(Page $page, Field $field) {
  
    /** @var Modules $modules */
    $modules = $this->wire('modules');

    $inputfieldClass = $field->get('inputfieldClass');
    $inputfieldClass = $inputfieldClass ? $inputfieldClass : 'InputfieldSelect';
    
    /** @var InputfieldSelect $inputfield */
    $inputfield = $modules->get($inputfieldClass); 
    if(!$inputfield) $inputfield = $this->modules->get('InputfieldSelect'); 

    $inputfield->attr('name', $field->name); 
    $inputfield->class = $this->className();
    $options = array();

    foreach($modules as $module) {
      $found = false; 
      $ns = $this->modules->getModuleNamespace($module);
      $parents = wireClassParents($ns ? "$ns$module" : "$module"); 
      $moduleTypes = $field->get('moduleTypes');
      if($moduleTypes) foreach($moduleTypes as $moduleType) {
        if(in_array($moduleType, $parents)) { 
          $found = true; 
          break;
        }
      }
      if(!$found) continue; 
      $labelField = $field->get('labelField');
      if($labelField === 'title') {
        $info = $modules->getModuleInfo($module);
        $label = !empty($info['title']) ? $info['title'] : (string) $module;
      } else if($labelField === 'title-summary') {
        $info = $modules->getModuleInfoVerbose($module);
        $label = !empty($info['title']) ? $info['title'] : (string) $module;
        if(!empty($info['summary'])) $label .= " [span.detail] • " . $info['summary'] . ' [/span]';
      } else {
        $label = (string) $module; 
      }

      $options[$label] = $module; 
    }

    ksort($options); 
    
    if($inputfieldClass == 'InputfieldRadios' && $field->get('showNoneOption')) {
      $inputfield->addOption(0, $this->_('None'));
    }

    foreach($options as $label => $module) {
      $inputfield->addOption((string) $module, $label); 
    }

    return $inputfield; 
  }

  public function getDatabaseSchema(Field $field) {
    $schema = parent::getDatabaseSchema($field); 
    $schema['data'] = 'int NOT NULL';
    return $schema;
  }

  public function ___getConfigInputfields(Field $field) {

    $inputfields = parent::___getConfigInputfields($field); 
    $lastType = '';

    /** @var InputfieldCheckboxes $f */
    $f = $this->modules->get("InputfieldCheckboxes"); 
    $f->attr('name', 'moduleTypes'); 
    
    foreach($this->modules as $module) {
      if(strpos($module->className(), 'AdminTheme') === 0) {
        $matches = array('', 'AdminTheme');
      } else {
        if(!preg_match('/^([A-Za-z][a-z0-9_]+)/', $module->className(), $matches)) continue;
      }
      $moduleType = $matches[1];
      if($moduleType == $lastType) continue;  
      $f->addOption($moduleType); 
      $lastType = $moduleType; 
    }

    $moduleTypes = $field->get('moduleTypes');
    if(!is_array($moduleTypes)) $moduleTypes = array();
    
    $f->attr('value', $moduleTypes);
    $f->label = $this->_('Module Types');
    $f->description = $this->_('Check all of the module types that may be selectable in this field.');
    $inputfields->append($f); 

    /** @var InputfieldCheckbox $f */
    $f = $this->modules->get("InputfieldCheckbox"); 
    $f->attr('name', 'instantiateModule'); 
    $f->label = $this->_('Make this field an instance of the selected module?'); 
    $f->description = $this->_('If checked, the field value will be an actual instance of the selected module. If not checked, the field value will be a string containing the class name of the module.'); // instantiate module description
    if($field->get('instantiateModule')) $f->attr('checked', 'checked'); 
    $inputfields->add($f); 

    /** @var InputfieldRadios $f */
    $f = $this->modules->get('InputfieldRadios'); 
    $f->label = $this->_('Options Label'); 
    $f->attr('name', 'labelField'); 
    $f->addOption('', $this->_('Name')); 
    $f->addOption('title', $this->_('Title'));
    $f->addOption('title-summary', $this->_('Title and summary'));
    $f->attr('value', $field->get('labelField')); 
    $f->columnWidth = 50; 
    $inputfields->add($f);

    /** @var InputfieldRadios $f */
    $f = $this->modules->get('InputfieldRadios'); 
    $f->label = $this->_('Input Type'); 
    $f->attr('name', 'inputfieldClass'); 
    $f->addOption('', $this->_('Select')); 
    $f->addOption('InputfieldRadios', $this->_('Radios')); 
    $f->columnWidth = 50;
    $f->attr('value', $field->get('inputfieldClass'));
    $inputfields->add($f); 
  
    /** @var InputfieldCheckbox $f */
    $f = $this->modules->get('InputfieldCheckbox');
    $f->label = $this->_('Show a “None” option?');
    $f->attr('name', 'showNoneOption');
    if($field->get('showNoneOption')) $f->attr('checked', 'checked'); 
    $f->showIf = 'inputfieldClass=InputfieldRadios';
    $inputfields->add($f);
  
    /** @var InputfieldRadios $f */
    $f = $this->modules->get('InputfieldRadios');
    $f->attr('name', 'blankType');
    $f->label = $this->_('Blank value type');
    $f->addOption('null', 'Null');
    $f->addOption('zero', 'Integer 0');
    $f->addOption('false', 'Boolean false');
    $f->addOption('placeholder', 'ModulePlaceholder instance');
    $f->attr('value', $field->get('blankType')); 
    $inputfields->add($f);

    return $inputfields;      
  }

  public function ___getCompatibleFieldtypes(Field $field) {
    $fieldtypes = $this->wire(new Fieldtypes());
    foreach($this->wire('fieldtypes') as $fieldtype) {
      if($fieldtype instanceof FieldtypeModule) $fieldtypes->add($fieldtype);
    }
    return $fieldtypes;
  }
}