/**
  * Custom processing for the options string in getConfigInputfields
  * 
  * Detects and confirms option deletions. 
  *
  * @param Inputfield $inputfield For the _options inputfield
  * @throws WireException
  *
  */
 protected function process(Inputfield $inputfield)
 {
     $value = $this->wire('input')->post('_options');
     if ($this->wire('process') != 'ProcessField' || !$this->wire('user')->isSuperuser()) {
         return;
     }
     $ns = "{$this}{$this->field}";
     // namespace for session
     if (!is_null($value)) {
         // _options has been posted
         if ($this->manager->useLanguages() && $inputfield->useLanguages) {
             // multi-language
             $valuesPerLanguage = array();
             $changed = false;
             foreach ($this->wire('languages') as $language) {
                 $key = $language->isDefault() ? "_options" : "_options__{$language}";
                 $valuesPerLanguage[$language->id] = $this->wire('input')->post($key);
                 $key = $language->isDefault() ? "value" : "value{$language}";
                 if ($inputfield->{$key} != $valuesPerLanguage[$language->id]) {
                     $changed = true;
                 }
             }
             if ($changed) {
                 $this->manager->setOptionsStringLanguages($this->field, $valuesPerLanguage, false);
             }
         } else {
             // non multi-language
             if ($value != $inputfield->attr('value')) {
                 $this->manager->setOptionsString($this->field, $value, false);
             }
         }
         $removedOptionIDs = $this->manager->getRemovedOptionIDs($this->field);
         // identified for removal
         if (count($removedOptionIDs)) {
             // stuff in session for next request
             $this->wire('session')->set($ns, 'removedOptionIDs', $removedOptionIDs);
         }
         $deleteOptionIDs = $this->wire('input')->post('_delete_options');
         $deleteConfirm = (int) $this->wire('input')->post('_delete_confirm');
         if ($deleteOptionIDs && $deleteConfirm) {
             // confirmed deleted
             if (!ctype_digit(str_replace(',', '', $deleteOptionIDs))) {
                 throw new WireException("Invalid deleteOptionIDs");
             }
             $deleteOptionIDs = explode(',', $deleteOptionIDs);
             foreach ($deleteOptionIDs as $key => $value) {
                 $deleteOptionIDs[$key] = (int) $value;
             }
             $this->manager->deleteOptionsByID($this->field, $deleteOptionIDs);
         }
     } else {
         // options not posted, check if there are any pending session activities
         $removedOptionIDs = $this->wire('session')->get($ns, 'removedOptionIDs');
         if (count($removedOptionIDs)) {
             $f = $this->wire('modules')->get('InputfieldHidden');
             $f->attr('name', '_delete_options');
             $f->attr('value', implode(',', $removedOptionIDs));
             $this->inputfields->prepend($f);
             // setup for confirmation
             $f = $this->wire('modules')->get('InputfieldCheckbox');
             $f->attr('name', '_delete_confirm');
             $f->label = $this->_('Please confirm that you want to delete options');
             $f->label2 = $this->_n('Delete this option', 'Delete these options', count($removedOptionIDs));
             $this->warning($f->label);
             $removeOptions = $this->manager->getOptionsByID($this->field, $removedOptionIDs);
             $delimiter = $this->_('DELETE:') . ' ';
             $f->description .= $delimiter . $removeOptions->implode("\n{$delimiter}", 'title');
             // collapse other inputfields since we prefer them to focus on this one only for now
             foreach ($this->inputfields as $i) {
                 $i->collapsed = Inputfield::collapsedYes;
             }
             // add our confirmation field
             $this->inputfields->prepend($f);
             // was stuffed in session from previous request, unset it now since this is a one time thing
             $this->wire('session')->remove($ns, 'removedOptionIDs');
         }
     }
 }
 /**
  * Returns whether or not the given Inputfield should be processed by processInput()
  * 
  * When an $inputfield has a 'showIf' property, then this returns false, but it queues
  * the field in the delayedChildren array for later processing. The root container should
  * temporarily remove the 'showIf' property of inputfields they want processed. 
  * 
  * @param Inputfield $inputfield
  * @return bool
  * 
  */
 public function isProcessable(Inputfield $inputfield)
 {
     if (!$inputfield->editable()) {
         return false;
     }
     // visibility settings that aren't saveable
     static $skipTypes = array(Inputfield::collapsedHidden, Inputfield::collapsedLocked, Inputfield::collapsedNoLocked, Inputfield::collapsedYesLocked);
     $collapsed = (int) $inputfield->getSetting('collapsed');
     if (in_array($collapsed, $skipTypes)) {
         return false;
     }
     if (in_array($collapsed, array(Inputfield::collapsedYesAjax, Inputfield::collapsedBlankAjax))) {
         $processAjax = $this->wire('input')->post('processInputfieldAjax');
         if (is_array($processAjax) && in_array($inputfield->attr('id'), $processAjax)) {
             // field can be processed (convention used by InputfieldWrapper)
         } else {
             if ($collapsed == Inputfield::collapsedBlankAjax && !$inputfield->isEmpty()) {
                 // field can be processed because it is only collapsed if blank
             } else {
                 if (isset($_SERVER['HTTP_X_FIELDNAME']) && $_SERVER['HTTP_X_FIELDNAME'] == $inputfield->attr('name')) {
                     // field can be processed (convention used by ajax uploaded file and other ajax types)
                 } else {
                     // field was not rendered via ajax and thus can't be processed
                     return false;
                 }
             }
         }
     }
     // if dependencies aren't in use, we can skip the rest
     if ($this->useDependencies === false) {
         return true;
     }
     if (strlen($inputfield->getSetting('showIf')) || $inputfield->getSetting('required') && strlen($inputfield->getSetting('requiredIf'))) {
         $name = $inputfield->attr('name');
         if (!$name) {
             $name = $inputfield->attr('id');
             if (!$name) {
                 $name = $this->wire('sanitizer')->fieldName($inputfield->label);
             }
             $inputfield->attr('name', $name);
         }
         $this->delayedChildren[$name] = $inputfield;
         return false;
     }
     return true;
 }
 /**
  * Returns whether or not the given Inputfield should be processed by processInput()
  * 
  * When an $inputfield has a 'showIf' property, then this returns false, but it queues
  * the field in the delayedChildren array for later processing. The root container should
  * temporarily remove the 'showIf' property of inputfields they want processed. 
  * 
  * @param Inputfield $inputfield
  * @return bool
  * 
  */
 protected function isProcessable(Inputfield $inputfield)
 {
     // skip over collapsedHidden or collapsedLocked inputfields, beacuse they are not saveable
     if ($inputfield->collapsed === Inputfield::collapsedHidden) {
         return false;
     }
     if ($inputfield->collapsed === Inputfield::collapsedLocked) {
         return false;
     }
     // if dependencies aren't in use, we can skip the rest
     //if(!$this->useDependencies) return true;
     if (strlen($inputfield->getSetting('showIf')) || $inputfield->getSetting('required') && strlen($inputfield->getSetting('requiredIf'))) {
         $name = $inputfield->attr('name');
         $this->delayedChildren[$name] = $inputfield;
         return false;
     }
     return true;
 }
 /**
  * Returns whether or not the given Inputfield should be processed by processInput()
  * 
  * When an $inputfield has a 'showIf' property, then this returns false, but it queues
  * the field in the delayedChildren array for later processing. The root container should
  * temporarily remove the 'showIf' property of inputfields they want processed. 
  * 
  * @param Inputfield $inputfield
  * @return bool
  * 
  */
 protected function isProcessable(Inputfield $inputfield)
 {
     // visibility settings that aren't saveable
     static $skipTypes = array(Inputfield::collapsedHidden, Inputfield::collapsedLocked, Inputfield::collapsedNoLocked, Inputfield::collapsedYesLocked);
     if (in_array((int) $inputfield->getSetting('collapsed'), $skipTypes)) {
         return false;
     }
     // if dependencies aren't in use, we can skip the rest
     if ($this->useDependencies === false) {
         return true;
     }
     if (strlen($inputfield->getSetting('showIf')) || $inputfield->getSetting('required') && strlen($inputfield->getSetting('requiredIf'))) {
         $name = $inputfield->attr('name');
         if (!$name) {
             $name = $inputfield->attr('id');
             if (!$name) {
                 $name = $this->wire('sanitizer')->fieldName($inputfield->label);
             }
             $inputfield->attr('name', $name);
         }
         $this->delayedChildren[$name] = $inputfield;
         return false;
     }
     return true;
 }
 /**
  * Returns whether or not the given Inputfield should be processed by processInput()
  * 
  * When an $inputfield has a 'showIf' property, then this returns false, but it queues
  * the field in the delayedChildren array for later processing. The root container should
  * temporarily remove the 'showIf' property of inputfields they want processed. 
  * 
  * @param Inputfield $inputfield
  * @return bool
  * 
  */
 protected function isProcessable(Inputfield $inputfield)
 {
     // skip over collapsedHidden or collapsedLocked inputfields, beacuse they are not saveable
     if ($inputfield->collapsed === Inputfield::collapsedHidden) {
         return false;
     }
     if ($inputfield->collapsed === Inputfield::collapsedNoLocked) {
         return false;
     }
     if ($inputfield->collapsed === Inputfield::collapsedYesLocked) {
         return false;
     }
     // if dependencies aren't in use, we can skip the rest
     if ($this->useDependencies === false) {
         return true;
     }
     if (strlen($inputfield->getSetting('showIf')) || $inputfield->getSetting('required') && strlen($inputfield->getSetting('requiredIf'))) {
         $name = $inputfield->attr('name');
         if (!$name) {
             $name = $inputfield->attr('id');
             if (!$name) {
                 $name = $this->wire('sanitizer')->fieldName($inputfield->label);
             }
             $inputfield->attr('name', $name);
         }
         $this->delayedChildren[$name] = $inputfield;
         return false;
     }
     return true;
 }