public function importEventsFromSource(PhabricatorUser $viewer, PhabricatorCalendarImport $import, $should_queue)
 {
     $uri_key = PhabricatorCalendarImportICSURITransaction::PARAMKEY_URI;
     $uri = $import->getParameter($uri_key);
     PhabricatorSystemActionEngine::willTakeAction(array($viewer->getPHID()), new PhabricatorFilesOutboundRequestAction(), 1);
     $file = PhabricatorFile::newFromFileDownload($uri, array('viewPolicy' => PhabricatorPolicies::POLICY_NOONE, 'authorPHID' => $import->getAuthorPHID(), 'canCDN' => true));
     $import->newLogMessage(PhabricatorCalendarImportFetchLogType::LOGTYPE, array('file.phid' => $file->getPHID()));
     $data = $file->loadFileData();
     if ($should_queue && $this->shouldQueueDataImport($data)) {
         return $this->queueDataImport($import, $data);
     }
     return $this->importICSData($viewer, $import, $data);
 }
 public function importEventsFromSource(PhabricatorUser $viewer, PhabricatorCalendarImport $import, $should_queue)
 {
     $phid_key = PhabricatorCalendarImportICSFileTransaction::PARAMKEY_FILE;
     $file_phid = $import->getParameter($phid_key);
     $file = id(new PhabricatorFileQuery())->setViewer($viewer)->withPHIDs(array($file_phid))->executeOne();
     if (!$file) {
         throw new Exception(pht('Unable to load file ("%s") for import.', $file_phid));
     }
     $data = $file->loadFileData();
     if ($should_queue && $this->shouldQueueDataImport($data)) {
         return $this->queueDataImport($import, $data);
     }
     return $this->importICSData($viewer, $import, $data);
 }
 protected final function importICSData(PhabricatorUser $viewer, PhabricatorCalendarImport $import, $data)
 {
     $parser = new PhutilICSParser();
     try {
         $document = $parser->parseICSData($data);
     } catch (PhutilICSParserException $ex) {
         // TODO: In theory, it would be nice to store these in a fully abstract
         // form so they can be translated at display time. As-is, we'll store the
         // error messages in whatever language we were using when the parser
         // failure occurred.
         $import->newLogMessage(PhabricatorCalendarImportICSLogType::LOGTYPE, array('ics.code' => $ex->getParserFailureCode(), 'ics.message' => $ex->getMessage()));
         $document = null;
     }
     foreach ($parser->getWarnings() as $warning) {
         $import->newLogMessage(PhabricatorCalendarImportICSWarningLogType::LOGTYPE, array('ics.warning.code' => $warning['code'], 'ics.warning.line' => $warning['line'], 'ics.warning.text' => $warning['text'], 'ics.warning.message' => $warning['message']));
     }
     return $this->importEventDocument($viewer, $import, $document);
 }
 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;
 }
 public function handleRequest(AphrontRequest $request)
 {
     $viewer = $request->getViewer();
     if (!$request->validateCSRF()) {
         return new Aphront400Response();
     }
     $cancel_uri = $this->getApplicationURI();
     $ids = $request->getStrList('h');
     if ($ids) {
         $files = id(new PhabricatorFileQuery())->setViewer($viewer)->withIDs($ids)->setRaisePolicyExceptions(true)->execute();
     } else {
         $files = array();
     }
     if (!$files) {
         return $this->newDialog()->setTitle(pht('Nothing Uploaded'))->appendParagraph(pht('Drag and drop .ics files to upload them and import them into ' . 'Calendar.'))->addCancelButton($cancel_uri, pht('Done'));
     }
     $engine = new PhabricatorCalendarICSFileImportEngine();
     $imports = array();
     foreach ($files as $file) {
         $import = PhabricatorCalendarImport::initializeNewCalendarImport($viewer, clone $engine);
         $xactions = array();
         $xactions[] = id(new PhabricatorCalendarImportTransaction())->setTransactionType(PhabricatorCalendarImportICSFileTransaction::TRANSACTIONTYPE)->setNewValue($file->getPHID());
         $editor = id(new PhabricatorCalendarImportEditor())->setActor($viewer)->setContinueOnNoEffect(true)->setContinueOnMissingFields(true)->setContentSourceFromRequest($request);
         $editor->applyTransactions($import, $xactions);
         $imports[] = $import;
     }
     $import_phids = mpull($imports, 'getPHID');
     $events = id(new PhabricatorCalendarEventQuery())->setViewer($viewer)->withImportSourcePHIDs($import_phids)->execute();
     if (count($events) == 1) {
         // The user imported exactly one event. This is consistent with dropping
         // a .ics file from an email; just take them to the event.
         $event = head($events);
         $next_uri = $event->getURI();
     } else {
         if (count($imports) > 1) {
             // The user imported multiple different files. Take them to a summary
             // list of generated import activity.
             $source_phids = implode(',', $import_phids);
             $next_uri = '/calendar/import/log/?importSourcePHIDs=' . $source_phids;
         } else {
             // The user imported one file, which had zero or more than one event.
             // Take them to the import detail page.
             $import = head($imports);
             $next_uri = $import->getURI();
         }
     }
     return id(new AphrontRedirectResponse())->setURI($next_uri);
 }
 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;
 }
 protected final function queueDataImport(PhabricatorCalendarImport $import, $data)
 {
     $import->newLogMessage(PhabricatorCalendarImportQueueLogType::LOGTYPE, array('data.size' => strlen($data), 'data.limit' => self::QUEUE_BYTE_LIMIT));
     // When we queue on this pathway, we're queueing in response to an explicit
     // user action (like uploading a big `.ics` file), so we queue at normal
     // priority instead of bulk/import priority.
     PhabricatorWorker::scheduleTask('PhabricatorCalendarImportReloadWorker', array('importPHID' => $import->getPHID(), 'via' => PhabricatorCalendarImportReloadWorker::VIA_BACKGROUND), array('objectPHID' => $import->getPHID()));
 }
 private function buildImportedEvents(PhabricatorCalendarImport $import)
 {
     $viewer = $this->getViewer();
     $engine = id(new PhabricatorCalendarEventSearchEngine())->setViewer($viewer);
     $saved = $engine->newSavedQuery()->setParameter('importSourcePHIDs', array($import->getPHID()));
     $pager = $engine->newPagerForSavedQuery($saved);
     $pager->setPageSize(25);
     $query = $engine->buildQueryFromSavedQuery($saved);
     $results = $engine->executeQuery($query, $pager);
     $view = $engine->renderResults($results, $saved);
     $list = $view->getObjectList();
     $list->setNoDataString(pht('No imported events.'));
     $all_uri = $this->getApplicationURI();
     $all_uri = (string) id(new PhutilURI($all_uri))->setQueryParam('importSourcePHID', $import->getPHID())->setQueryParam('display', 'list');
     $all_button = id(new PHUIButtonView())->setTag('a')->setText(pht('View All'))->setIcon('fa-search')->setHref($all_uri);
     $header = id(new PHUIHeaderView())->setHeader(pht('Imported Events'))->addActionLink($all_button);
     return id(new PHUIObjectBoxView())->setHeader($header)->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)->setObjectList($list);
 }