public function validateTransactions($object, array $xactions)
 {
     $errors = array();
     $frequency_map = PhabricatorCalendarImport::getTriggerFrequencyMap();
     $valid = array_keys($frequency_map);
     $valid = array_fuse($valid);
     foreach ($xactions as $xaction) {
         $value = $xaction->getNewValue();
         if (!isset($valid[$value])) {
             $errors[] = $this->newInvalidError(pht('Import frequency "%s" is not valid. Valid frequences are: %s.', $value, implode(', ', $valid)), $xaction);
         }
     }
     return $errors;
 }
 protected function buildCustomEditFields($object)
 {
     $viewer = $this->getViewer();
     $engine = $object->getEngine();
     $can_trigger = $engine->supportsTriggers($object);
     $fields = array(id(new PhabricatorTextEditField())->setKey('name')->setLabel(pht('Name'))->setDescription(pht('Name of the import.'))->setTransactionType(PhabricatorCalendarImportNameTransaction::TRANSACTIONTYPE)->setConduitDescription(pht('Rename the import.'))->setConduitTypeDescription(pht('New import name.'))->setPlaceholder($object->getDisplayName())->setValue($object->getName()), id(new PhabricatorBoolEditField())->setKey('disabled')->setOptions(pht('Active'), pht('Disabled'))->setLabel(pht('Disabled'))->setDescription(pht('Disable the import.'))->setTransactionType(PhabricatorCalendarImportDisableTransaction::TRANSACTIONTYPE)->setIsConduitOnly(true)->setConduitDescription(pht('Disable or restore the import.'))->setConduitTypeDescription(pht('True to cancel the import.'))->setValue($object->getIsDisabled()), id(new PhabricatorBoolEditField())->setKey('delete')->setLabel(pht('Delete Imported Events'))->setDescription(pht('Delete all events from this source.'))->setTransactionType(PhabricatorCalendarImportDisableTransaction::TRANSACTIONTYPE)->setIsConduitOnly(true)->setConduitDescription(pht('Disable or restore the import.'))->setConduitTypeDescription(pht('True to delete imported events.'))->setValue(false), id(new PhabricatorBoolEditField())->setKey('reload')->setLabel(pht('Reload Import'))->setDescription(pht('Reload events imported from this source.'))->setTransactionType(PhabricatorCalendarImportDisableTransaction::TRANSACTIONTYPE)->setIsConduitOnly(true)->setConduitDescription(pht('Disable or restore the import.'))->setConduitTypeDescription(pht('True to reload the import.'))->setValue(false));
     if ($can_trigger) {
         $frequency_map = PhabricatorCalendarImport::getTriggerFrequencyMap();
         $frequency_options = ipull($frequency_map, 'name');
         $fields[] = id(new PhabricatorSelectEditField())->setKey('frequency')->setLabel(pht('Update Automatically'))->setDescription(pht('Configure an automatic update frequncy.'))->setTransactionType(PhabricatorCalendarImportFrequencyTransaction::TRANSACTIONTYPE)->setConduitDescription(pht('Set the automatic update frequency.'))->setConduitTypeDescription(pht('Update frequency constant.'))->setValue($object->getTriggerFrequency())->setOptions($frequency_options);
     }
     $import_engine = $object->getEngine();
     foreach ($import_engine->newEditEngineFields($this, $object) as $field) {
         $fields[] = $field;
     }
     return $fields;
 }
 private function buildPropertySection(PhabricatorCalendarImport $import)
 {
     $viewer = $this->getViewer();
     $properties = id(new PHUIPropertyListView())->setViewer($viewer);
     $engine = $import->getEngine();
     $properties->addProperty(pht('Source Type'), $engine->getImportEngineTypeName());
     if ($import->getIsDisabled()) {
         $auto_updates = phutil_tag('em', array(), pht('Import Disabled'));
         $has_trigger = false;
     } else {
         $frequency = $import->getTriggerFrequency();
         $frequency_map = PhabricatorCalendarImport::getTriggerFrequencyMap();
         $frequency_names = ipull($frequency_map, 'name');
         $auto_updates = idx($frequency_names, $frequency, $frequency);
         if ($frequency == PhabricatorCalendarImport::FREQUENCY_ONCE) {
             $has_trigger = false;
             $auto_updates = phutil_tag('em', array(), $auto_updates);
         } else {
             $has_trigger = true;
         }
     }
     $properties->addProperty(pht('Automatic Updates'), $auto_updates);
     if ($has_trigger) {
         $trigger = id(new PhabricatorWorkerTriggerQuery())->setViewer($viewer)->withPHIDs(array($import->getTriggerPHID()))->needEvents(true)->executeOne();
         if (!$trigger) {
             $next_trigger = phutil_tag('em', array(), pht('Invalid Trigger'));
         } else {
             $now = PhabricatorTime::getNow();
             $next_epoch = $trigger->getNextEventPrediction();
             $next_trigger = pht('%s (%s)', phabricator_datetime($next_epoch, $viewer), phutil_format_relative_time($next_epoch - $now));
         }
         $properties->addProperty(pht('Next Update'), $next_trigger);
     }
     $engine->appendImportProperties($viewer, $import, $properties);
     return $properties;
 }