public function deleteFile($handle) { $engine = new PhabricatorDestructionEngine(); $chunks = $this->loadAllChunks($handle, true); foreach ($chunks as $chunk) { $engine->destroyObject($chunk); } }
public function applyExternalEffects($object, $value) { $events = id(new PhabricatorCalendarEventQuery())->setViewer($this->getActor())->withImportSourcePHIDs(array($object->getPHID()))->execute(); $engine = new PhabricatorDestructionEngine(); foreach ($events as $event) { $engine->destroyObject($event); } }
public function destroyObjectPermanently(PhabricatorDestructionEngine $engine) { $bindings = id(new AlmanacBindingQuery())->setViewer($engine->getViewer())->withInterfacePHIDs(array($this->getPHID()))->execute(); foreach ($bindings as $binding) { $engine->destroyObject($binding); } $this->delete(); }
public function destroyObject(PhabricatorDestructionEngine $engine, $object) { $template = $object->getApplicationTransactionTemplate(); $xactions = $template->loadAllWhere('objectPHID = %s', $object->getPHID()); foreach ($xactions as $xaction) { $engine->destroyObject($xaction); } }
public function destroyObject(PhabricatorDestructionEngine $engine, $object) { $object_phid = $object->getPHID(); $transcripts = id(new HeraldTranscript())->loadAllWhere('objectPHID = %s', $object_phid); foreach ($transcripts as $transcript) { $engine->destroyObject($transcript); } }
public function destroyObjectPermanently(PhabricatorDestructionEngine $engine) { $interfaces = id(new AlmanacInterfaceQuery())->setViewer($engine->getViewer())->withNetworkPHIDs(array($this->getPHID()))->execute(); foreach ($interfaces as $interface) { $engine->destroyObject($interface); } $this->delete(); }
protected function collectGarbage() { $file_requests = id(new PhabricatorFileExternalRequest())->loadAllWhere('ttl < %d LIMIT 100', PhabricatorTime::getNow()); $engine = new PhabricatorDestructionEngine(); foreach ($file_requests as $request) { $engine->destroyObject($request); } return count($file_requests) == 100; }
public function destroyObjectPermanently(PhabricatorDestructionEngine $engine) { $file_phid = $this->getFilePHID(); $file = id(new PhabricatorFileQuery())->setViewer($engine->getViewer())->withPHIDs(array($file_phid))->executeOne(); if ($file) { $engine->destroyObject($file); } $this->delete(); }
public function destroyObjectPermanently(PhabricatorDestructionEngine $engine) { $viewer = $engine->getViewer(); $this->openTransaction(); $packages = id(new PhabricatorPackagesPackageQuery())->setViewer($viewer)->withPublisherPHIDs(array($this->getPHID()))->execute(); foreach ($packages as $package) { $engine->destroyObject($package); } $this->delete(); $this->saveTransaction(); }
public function handleRequest(AphrontRequest $request) { $show_prototypes = PhabricatorEnv::getEnvConfig('phabricator.show-prototypes'); if (!$show_prototypes) { throw new Exception(pht('Show prototypes is disabled. Set `phabricator.show-prototypes` to `true` to use the image proxy')); } $viewer = $request->getViewer(); $img_uri = $request->getStr('uri'); // Validate the URI before doing anything PhabricatorEnv::requireValidRemoteURIForLink($img_uri); $uri = new PhutilURI($img_uri); $proto = $uri->getProtocol(); if (!in_array($proto, array('http', 'https'))) { throw new Exception(pht('The provided image URI must be either http or https')); } // Check if we already have the specified image URI downloaded $cached_request = id(new PhabricatorFileExternalRequest())->loadOneWhere('uriIndex = %s', PhabricatorHash::digestForIndex($img_uri)); if ($cached_request) { return $this->getExternalResponse($cached_request); } $ttl = PhabricatorTime::getNow() + phutil_units('7 days in seconds'); $external_request = id(new PhabricatorFileExternalRequest())->setURI($img_uri)->setTTL($ttl); $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites(); // Cache missed so we'll need to validate and download the image try { // Rate limit outbound fetches to make this mechanism less useful for // scanning networks and ports. PhabricatorSystemActionEngine::willTakeAction(array($viewer->getPHID()), new PhabricatorFilesOutboundRequestAction(), 1); $file = PhabricatorFile::newFromFileDownload($uri, array('viewPolicy' => PhabricatorPolicies::POLICY_NOONE, 'canCDN' => true)); if (!$file->isViewableImage()) { $mime_type = $file->getMimeType(); $engine = new PhabricatorDestructionEngine(); $engine->destroyObject($file); $file = null; throw new Exception(pht('The URI "%s" does not correspond to a valid image file, got ' . 'a file with MIME type "%s". You must specify the URI of a ' . 'valid image file.', $uri, $mime_type)); } else { $file->save(); } $external_request->setIsSuccessful(true)->setFilePHID($file->getPHID())->save(); unset($unguarded); return $this->getExternalResponse($external_request); } catch (HTTPFutureHTTPResponseStatus $status) { $external_request->setIsSuccessful(false)->setResponseMessage($status->getMessage())->save(); return $this->getExternalResponse($external_request); } catch (Exception $ex) { // Not actually saving the request in this case $external_request->setResponseMessage($ex->getMessage()); return $this->getExternalResponse($external_request); } }
public function destroyObjectPermanently(PhabricatorDestructionEngine $engine) { $this->openTransaction(); $diffs = id(new DifferentialDiffQuery())->setViewer($engine->getViewer())->withRevisionIDs(array($this->getID()))->execute(); foreach ($diffs as $diff) { $engine->destroyObject($diff); } $conn_w = $this->establishConnection('w'); queryfx($conn_w, 'DELETE FROM %T WHERE revisionID = %d', self::TABLE_COMMIT, $this->getID()); // we have to do paths a little differentally as they do not have // an id or phid column for delete() to act on $dummy_path = new DifferentialAffectedPath(); queryfx($conn_w, 'DELETE FROM %T WHERE revisionID = %d', $dummy_path->getTableName(), $this->getID()); $this->delete(); $this->saveTransaction(); }
private function returnDeleteAddressResponse(AphrontRequest $request, PhutilURI $uri, $email_object_id) { $viewer = $this->getViewer(); $email_object = id(new PhabricatorMetaMTAApplicationEmailQuery())->setViewer($viewer)->withIDs(array($email_object_id))->requireCapabilities(array(PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT))->executeOne(); if (!$email_object) { return new Aphront404Response(); } if ($request->isDialogFormPost()) { $engine = new PhabricatorDestructionEngine(); $engine->destroyObject($email_object); return id(new AphrontRedirectResponse())->setURI($uri); } $dialog = id(new AphrontDialogView())->setUser($viewer)->addHiddenInput('delete', $email_object_id)->setTitle(pht('Delete Address'))->appendParagraph(pht('Are you sure you want to delete this email address?'))->addSubmitButton(pht('Delete'))->addCancelButton($uri); return id(new AphrontDialogResponse())->setDialog($dialog); }
protected function applyFinalEffects(PhabricatorLiskDAO $object, array $xactions) { $actor = $this->getActor(); // We import events when you create a source, or if you later reload it // explicitly. $should_reload = $this->getIsNewObject(); // We adjust the import trigger if you change the import frequency or // disable the import. $should_trigger = false; foreach ($xactions as $xaction) { $xaction_type = $xaction->getTransactionType(); switch ($xaction_type) { case PhabricatorCalendarImportReloadTransaction::TRANSACTIONTYPE: $should_reload = true; break; case PhabricatorCalendarImportFrequencyTransaction::TRANSACTIONTYPE: $should_trigger = true; break; case PhabricatorCalendarImportDisableTransaction::TRANSACTIONTYPE: $should_trigger = true; break; } } if ($should_reload) { $import_engine = $object->getEngine(); $import_engine->importEventsFromSource($actor, $object, true); } if ($should_trigger) { $trigger_phid = $object->getTriggerPHID(); if ($trigger_phid) { $trigger = id(new PhabricatorWorkerTriggerQuery())->setViewer($actor)->withPHIDs(array($trigger_phid))->executeOne(); if ($trigger) { $engine = new PhabricatorDestructionEngine(); $engine->destroyObject($trigger); } } $frequency = $object->getTriggerFrequency(); $now = PhabricatorTime::getNow(); switch ($frequency) { case PhabricatorCalendarImport::FREQUENCY_ONCE: $clock = null; break; case PhabricatorCalendarImport::FREQUENCY_HOURLY: $clock = new PhabricatorMetronomicTriggerClock(array('period' => phutil_units('1 hour in seconds'))); break; case PhabricatorCalendarImport::FREQUENCY_DAILY: $clock = new PhabricatorDailyRoutineTriggerClock(array('start' => $now)); break; default: throw new Exception(pht('Unknown import trigger frequency "%s".', $frequency)); } // If the object has been disabled, don't write a new trigger. if ($object->getIsDisabled()) { $clock = null; } if ($clock) { $trigger_action = new PhabricatorScheduleTaskTriggerAction(array('class' => 'PhabricatorCalendarImportReloadWorker', 'data' => array('importPHID' => $object->getPHID(), 'via' => PhabricatorCalendarImportReloadWorker::VIA_TRIGGER), 'options' => array('objectPHID' => $object->getPHID(), 'priority' => PhabricatorWorker::PRIORITY_BULK))); $trigger_phid = PhabricatorPHID::generateNewPHID(PhabricatorWorkerTriggerPHIDType::TYPECONST); $object->setTriggerPHID($trigger_phid)->save(); $trigger = id(new PhabricatorWorkerTrigger())->setClock($clock)->setAction($trigger_action)->setPHID($trigger_phid)->save(); } else { $object->setTriggerPHID(null)->save(); } } return $xactions; }
public function destroyObjectPermanently(PhabricatorDestructionEngine $engine) { $phid = $this->getPHID(); $this->openTransaction(); $this->delete(); PhabricatorRepositoryURIIndex::updateRepositoryURIs($phid, array()); $books = id(new DivinerBookQuery())->setViewer($engine->getViewer())->withRepositoryPHIDs(array($phid))->execute(); foreach ($books as $book) { $engine->destroyObject($book); } $atoms = id(new DivinerAtomQuery())->setViewer($engine->getViewer())->withRepositoryPHIDs(array($phid))->execute(); foreach ($atoms as $atom) { $engine->destroyObject($atom); } $lfs_refs = id(new PhabricatorRepositoryGitLFSRefQuery())->setViewer($engine->getViewer())->withRepositoryPHIDs(array($phid))->execute(); foreach ($lfs_refs as $ref) { $engine->destroyObject($ref); } $this->saveTransaction(); }
public function destroyObjectPermanently(PhabricatorDestructionEngine $engine) { $this->openTransaction(); $diffs = id(new DifferentialDiffQuery())->setViewer(PhabricatorUser::getOmnipotentUser())->withRevisionIDs(array($this->getID()))->execute(); foreach ($diffs as $diff) { $engine->destroyObject($diff); } $conn_w = $this->establishConnection('w'); queryfx($conn_w, 'DELETE FROM %T WHERE revisionID = %d', self::TABLE_COMMIT, $this->getID()); try { $inlines = id(new DifferentialInlineCommentQuery())->withRevisionIDs(array($this->getID()))->execute(); foreach ($inlines as $inline) { $inline->delete(); } } catch (PhabricatorEmptyQueryException $ex) { // TODO: There's still some funky legacy wrapping going on here, and // we might catch a raw query exception. } // we have to do paths a little differentally as they do not have // an id or phid column for delete() to act on $dummy_path = new DifferentialAffectedPath(); queryfx($conn_w, 'DELETE FROM %T WHERE revisionID = %d', $dummy_path->getTableName(), $this->getID()); $this->delete(); $this->saveTransaction(); }
public function destroyObjectPermanently(PhabricatorDestructionEngine $engine) { $this->openTransaction(); $this->delete(); $columns = id(new PhabricatorProjectColumn())->loadAllWhere('projectPHID = %s', $this->getPHID()); foreach ($columns as $column) { $engine->destroyObject($column); } $slugs = id(new PhabricatorProjectSlug())->loadAllWhere('projectPHID = %s', $this->getPHID()); foreach ($slugs as $slug) { $slug->delete(); } $this->saveTransaction(); }
protected final function importEventDocument(PhabricatorUser $viewer, PhabricatorCalendarImport $import, PhutilCalendarRootNode $root = null) { $event_type = PhutilCalendarEventNode::NODETYPE; $nodes = array(); if ($root) { foreach ($root->getChildren() as $document) { foreach ($document->getChildren() as $node) { $node_type = $node->getNodeType(); if ($node_type != $event_type) { $import->newLogMessage(PhabricatorCalendarImportIgnoredNodeLogType::LOGTYPE, array('node.type' => $node_type)); continue; } $nodes[] = $node; } } } // Reject events which have dates outside of the range of a signed // 32-bit integer. We'll need to accommodate a wider range of events // eventually, but have about 20 years until it's an issue and we'll // all be dead by then. foreach ($nodes as $key => $node) { $dates = array(); $dates[] = $node->getStartDateTime(); $dates[] = $node->getEndDateTime(); $dates[] = $node->getCreatedDateTime(); $dates[] = $node->getModifiedDateTime(); $rrule = $node->getRecurrenceRule(); if ($rrule) { $dates[] = $rrule->getUntil(); } $bad_date = false; foreach ($dates as $date) { if ($date === null) { continue; } $year = $date->getYear(); if ($year < 1970 || $year > 2037) { $bad_date = true; break; } } if ($bad_date) { $import->newLogMessage(PhabricatorCalendarImportEpochLogType::LOGTYPE, array()); unset($nodes[$key]); } } // Reject events which occur too frequently. Users do not normally define // these events and the UI and application make many assumptions which are // incompatible with events recurring once per second. foreach ($nodes as $key => $node) { $rrule = $node->getRecurrenceRule(); if (!$rrule) { // This is not a recurring event, so we don't need to check the // frequency. continue; } $scale = $rrule->getFrequencyScale(); if ($scale >= PhutilCalendarRecurrenceRule::SCALE_DAILY) { // This is a daily, weekly, monthly, or yearly event. These are // supported. } else { // This is an hourly, minutely, or secondly event. $import->newLogMessage(PhabricatorCalendarImportFrequencyLogType::LOGTYPE, array('frequency' => $rrule->getFrequency())); unset($nodes[$key]); } } $node_map = array(); foreach ($nodes as $node) { $full_uid = $this->getFullNodeUID($node); if (isset($node_map[$full_uid])) { $import->newLogMessage(PhabricatorCalendarImportDuplicateLogType::LOGTYPE, array('uid.full' => $full_uid)); continue; } $node_map[$full_uid] = $node; } // If we already know about some of these events and they were created // here, we're not going to import it again. This can happen if a user // exports an event and then tries to import it again. This is probably // not what they meant to do and this pathway generally leads to madness. $likely_phids = array(); foreach ($node_map as $full_uid => $node) { $uid = $node->getUID(); $matches = null; if (preg_match('/^(PHID-.*)@(.*)\\z/', $uid, $matches)) { $likely_phids[$full_uid] = $matches[1]; } } if ($likely_phids) { // NOTE: We're using the omnipotent viewer here because we don't want // to collide with events that already exist, even if you can't see // them. $events = id(new PhabricatorCalendarEventQuery())->setViewer(PhabricatorUser::getOmnipotentUser())->withPHIDs($likely_phids)->execute(); $events = mpull($events, null, 'getPHID'); foreach ($node_map as $full_uid => $node) { $phid = idx($likely_phids, $full_uid); if (!$phid) { continue; } $event = idx($events, $phid); if (!$event) { continue; } $import->newLogMessage(PhabricatorCalendarImportOriginalLogType::LOGTYPE, array('phid' => $event->getPHID())); unset($node_map[$full_uid]); } } if ($node_map) { $events = id(new PhabricatorCalendarEventQuery())->setViewer($viewer)->withImportAuthorPHIDs(array($import->getAuthorPHID()))->withImportUIDs(array_keys($node_map))->execute(); $events = mpull($events, null, 'getImportUID'); } else { $events = null; } $xactions = array(); $update_map = array(); $invitee_map = array(); $attendee_map = array(); foreach ($node_map as $full_uid => $node) { $event = idx($events, $full_uid); if (!$event) { $event = PhabricatorCalendarEvent::initializeNewCalendarEvent($viewer); } $event->setImportAuthorPHID($import->getAuthorPHID())->setImportSourcePHID($import->getPHID())->setImportUID($full_uid)->attachImportSource($import); $this->updateEventFromNode($viewer, $event, $node); $xactions[$full_uid] = $this->newUpdateTransactions($event, $node); $update_map[$full_uid] = $event; $attendee_map[$full_uid] = array(); $attendees = $node->getAttendees(); $private_index = 1; foreach ($attendees as $attendee) { // Generate a "name" for this attendee which is not an email address. // We avoid disclosing email addresses to be consistent with the rest // of the product. $name = $attendee->getName(); if (preg_match('/@/', $name)) { $name = new PhutilEmailAddress($name); $name = $name->getDisplayName(); } // If we don't have a name or the name still looks like it's an // email address, give them a dummy placeholder name. if (!strlen($name) || preg_match('/@/', $name)) { $name = pht('Private User %d', $private_index); $private_index++; } $attendee_map[$full_uid][$name] = $attendee; } } $attendee_names = array(); foreach ($attendee_map as $full_uid => $event_attendees) { foreach ($event_attendees as $name => $attendee) { $attendee_names[$name] = $attendee; } } if ($attendee_names) { $external_invitees = id(new PhabricatorCalendarExternalInviteeQuery())->setViewer($viewer)->withNames(array_keys($attendee_names))->execute(); $external_invitees = mpull($external_invitees, null, 'getName'); foreach ($attendee_names as $name => $attendee) { if (isset($external_invitees[$name])) { continue; } $external_invitee = id(new PhabricatorCalendarExternalInvitee())->setName($name)->setURI($attendee->getURI())->setSourcePHID($import->getPHID()); try { $external_invitee->save(); } catch (AphrontDuplicateKeyQueryException $ex) { $external_invitee = id(new PhabricatorCalendarExternalInviteeQuery())->setViewer($viewer)->withNames(array($name))->executeOne(); } $external_invitees[$name] = $external_invitee; } } // Reorder events so we create parents first. This allows us to populate // "instanceOfEventPHID" correctly. $insert_order = array(); foreach ($update_map as $full_uid => $event) { $parent_uid = $this->getParentNodeUID($node_map[$full_uid]); if ($parent_uid === null) { $insert_order[$full_uid] = $full_uid; continue; } if (empty($update_map[$parent_uid])) { // The parent was not present in this import, which means it either // does not exist or we're going to delete it anyway. We just drop // this node. $import->newLogMessage(PhabricatorCalendarImportOrphanLogType::LOGTYPE, array('uid.full' => $full_uid, 'uid.parent' => $parent_uid)); continue; } // Otherwise, we're going to insert the parent first, then insert // the child. $insert_order[$parent_uid] = $parent_uid; $insert_order[$full_uid] = $full_uid; } // TODO: Define per-engine content sources so this can say "via Upload" or // whatever. $content_source = PhabricatorContentSource::newForSource(PhabricatorWebContentSource::SOURCECONST); // NOTE: We're using the omnipotent user here because imported events are // otherwise immutable. $edit_actor = PhabricatorUser::getOmnipotentUser(); $update_map = array_select_keys($update_map, $insert_order); foreach ($update_map as $full_uid => $event) { $parent_uid = $this->getParentNodeUID($node_map[$full_uid]); if ($parent_uid) { $parent_phid = $update_map[$parent_uid]->getPHID(); } else { $parent_phid = null; } $event->setInstanceOfEventPHID($parent_phid); $event_xactions = $xactions[$full_uid]; $editor = id(new PhabricatorCalendarEventEditor())->setActor($edit_actor)->setActingAsPHID($import->getPHID())->setContentSource($content_source)->setContinueOnNoEffect(true)->setContinueOnMissingFields(true); $is_new = !$event->getID(); $editor->applyTransactions($event, $event_xactions); // We're just forcing attendees to the correct values here because // transactions intentionally don't let you RSVP for other users. This // might need to be turned into a special type of transaction eventually. $attendees = $attendee_map[$full_uid]; $old_map = $event->getInvitees(); $old_map = mpull($old_map, null, 'getInviteePHID'); $new_map = array(); foreach ($attendees as $name => $attendee) { $phid = $external_invitees[$name]->getPHID(); $invitee = idx($old_map, $phid); if (!$invitee) { $invitee = id(new PhabricatorCalendarEventInvitee())->setEventPHID($event->getPHID())->setInviteePHID($phid)->setInviterPHID($import->getPHID()); } switch ($attendee->getStatus()) { case PhutilCalendarUserNode::STATUS_ACCEPTED: $status = PhabricatorCalendarEventInvitee::STATUS_ATTENDING; break; case PhutilCalendarUserNode::STATUS_DECLINED: $status = PhabricatorCalendarEventInvitee::STATUS_DECLINED; break; case PhutilCalendarUserNode::STATUS_INVITED: default: $status = PhabricatorCalendarEventInvitee::STATUS_INVITED; break; } $invitee->setStatus($status); $invitee->save(); $new_map[$phid] = $invitee; } foreach ($old_map as $phid => $invitee) { if (empty($new_map[$phid])) { $invitee->delete(); } } $event->attachInvitees($new_map); $import->newLogMessage(PhabricatorCalendarImportUpdateLogType::LOGTYPE, array('new' => $is_new, 'phid' => $event->getPHID())); } if (!$update_map) { $import->newLogMessage(PhabricatorCalendarImportEmptyLogType::LOGTYPE, array()); } // Delete any events which are no longer present in the source. $updated_events = mpull($update_map, null, 'getPHID'); $source_events = id(new PhabricatorCalendarEventQuery())->setViewer($viewer)->withImportSourcePHIDs(array($import->getPHID()))->execute(); $engine = new PhabricatorDestructionEngine(); foreach ($source_events as $source_event) { if (isset($updated_events[$source_event->getPHID()])) { // We imported and updated this event, so keep it around. continue; } $import->newLogMessage(PhabricatorCalendarImportDeleteLogType::LOGTYPE, array('name' => $source_event->getName())); $engine->destroyObject($source_event); } }
public function destroyObjectPermanently(PhabricatorDestructionEngine $engine) { $this->openTransaction(); $answers = id(new PonderAnswer())->loadAllWhere('questionID = %d', $this->getID()); foreach ($answers as $answer) { $engine->destroyObject($answer); } $this->delete(); $this->saveTransaction(); }
public function destroyObjectPermanently(PhabricatorDestructionEngine $engine) { $viewer = $engine->getViewer(); $this->openTransaction(); $trigger_phid = $this->getTriggerPHID(); if ($trigger_phid) { $trigger = id(new PhabricatorWorkerTriggerQuery())->setViewer($viewer)->withPHIDs(array($trigger_phid))->executeOne(); if ($trigger) { $engine->destroyObject($trigger); } } $events = id(new PhabricatorCalendarEventQuery())->setViewer($viewer)->withImportSourcePHIDs(array($this->getPHID()))->execute(); foreach ($events as $event) { $engine->destroyObject($event); } $logs = id(new PhabricatorCalendarImportLogQuery())->setViewer($viewer)->withImportPHIDs(array($this->getPHID()))->execute(); foreach ($logs as $log) { $engine->destroyObject($log); } $this->delete(); $this->saveTransaction(); }
private function destroyAllSpaces() { PhabricatorSpacesNamespaceQuery::destroySpacesCache(); $spaces = $this->loadAllSpaces(); foreach ($spaces as $space) { $engine = new PhabricatorDestructionEngine(); $engine->destroyObject($space); } }
public function destroyObjectPermanently(PhabricatorDestructionEngine $engine) { $this->openTransaction(); $posts = id(new PhamePostQuery())->setViewer($engine->getViewer())->withBlogPHIDs(array($this->getPHID()))->execute(); foreach ($posts as $post) { $engine->destroyObject($post); } $this->delete(); $this->saveTransaction(); }
public function destroyObjectPermanently(PhabricatorDestructionEngine $engine) { $awards = id(new PhabricatorBadgesAwardQuery())->setViewer($engine->getViewer())->withBadgePHIDs(array($this->getPHID()))->execute(); foreach ($awards as $award) { $engine->destroyObject($award); } $this->openTransaction(); $this->delete(); $this->saveTransaction(); }
public function destroyObjectPermanently(PhabricatorDestructionEngine $engine) { $this->openTransaction(); $comment_template = null; try { $comment_template = $this->getApplicationTransactionCommentObject(); } catch (Exception $ex) { // Continue; no comments for these transactions. } if ($comment_template) { $comments = $comment_template->loadAllWhere('transactionPHID = %s', $this->getPHID()); foreach ($comments as $comment) { $engine->destroyObject($comment); } } $this->delete(); $this->saveTransaction(); }
public function handleRequest(AphrontRequest $request) { $viewer = $request->getViewer(); $id = $request->getURIData('id'); $this->requireApplicationCapability(PhabricatorMacroManageCapability::CAPABILITY); if ($id) { $macro = id(new PhabricatorMacroQuery())->setViewer($viewer)->withIDs(array($id))->needFiles(true)->executeOne(); if (!$macro) { return new Aphront404Response(); } } else { $macro = new PhabricatorFileImageMacro(); $macro->setAuthorPHID($viewer->getPHID()); } $errors = array(); $e_name = true; $e_file = null; $file = null; if ($request->isFormPost()) { $original = clone $macro; $new_name = null; if ($request->getBool('name_form') || !$macro->getID()) { $new_name = $request->getStr('name'); $macro->setName($new_name); if (!strlen($macro->getName())) { $errors[] = pht('Macro name is required.'); $e_name = pht('Required'); } else { if (!preg_match('/^[a-z0-9:_-]{3,}\\z/', $macro->getName())) { $errors[] = pht('Macro must be at least three characters long and contain only ' . 'lowercase letters, digits, hyphens, colons and underscores.'); $e_name = pht('Invalid'); } else { $e_name = null; } } } $uri = $request->getStr('url'); $engine = new PhabricatorDestructionEngine(); $file = null; if ($request->getFileExists('file')) { $file = PhabricatorFile::newFromPHPUpload($_FILES['file'], array('name' => $request->getStr('name'), 'authorPHID' => $viewer->getPHID(), 'isExplicitUpload' => true, 'canCDN' => true)); } else { if ($uri) { try { // Rate limit outbound fetches to make this mechanism less useful for // scanning networks and ports. PhabricatorSystemActionEngine::willTakeAction(array($viewer->getPHID()), new PhabricatorFilesOutboundRequestAction(), 1); $file = PhabricatorFile::newFromFileDownload($uri, array('name' => $request->getStr('name'), 'viewPolicy' => PhabricatorPolicies::POLICY_NOONE, 'isExplicitUpload' => true, 'canCDN' => true)); if (!$file->isViewableInBrowser()) { $mime_type = $file->getMimeType(); $engine->destroyObject($file); $file = null; throw new Exception(pht('The URI "%s" does not correspond to a valid image file, got ' . 'a file with MIME type "%s". You must specify the URI of a ' . 'valid image file.', $uri, $mime_type)); } else { $file->setAuthorPHID($viewer->getPHID())->save(); } } catch (HTTPFutureHTTPResponseStatus $status) { $errors[] = pht('The URI "%s" could not be loaded, got %s error.', $uri, $status->getStatusCode()); } catch (Exception $ex) { $errors[] = $ex->getMessage(); } } else { if ($request->getStr('phid')) { $file = id(new PhabricatorFileQuery())->setViewer($viewer)->withPHIDs(array($request->getStr('phid')))->executeOne(); } } } if ($file) { if (!$file->isViewableInBrowser()) { $errors[] = pht('You must upload an image.'); $e_file = pht('Invalid'); } else { $macro->setFilePHID($file->getPHID()); $macro->attachFile($file); $e_file = null; } } if (!$macro->getID() && !$file) { $errors[] = pht('You must upload an image to create a macro.'); $e_file = pht('Required'); } if (!$errors) { try { $xactions = array(); if ($new_name !== null) { $xactions[] = id(new PhabricatorMacroTransaction())->setTransactionType(PhabricatorMacroTransaction::TYPE_NAME)->setNewValue($new_name); } if ($file) { $xactions[] = id(new PhabricatorMacroTransaction())->setTransactionType(PhabricatorMacroTransaction::TYPE_FILE)->setNewValue($file->getPHID()); } $editor = id(new PhabricatorMacroEditor())->setActor($viewer)->setContinueOnNoEffect(true)->setContentSourceFromRequest($request); $xactions = $editor->applyTransactions($original, $xactions); $view_uri = $this->getApplicationURI('/view/' . $original->getID() . '/'); return id(new AphrontRedirectResponse())->setURI($view_uri); } catch (AphrontDuplicateKeyQueryException $ex) { throw $ex; $errors[] = pht('Macro name is not unique!'); $e_name = pht('Duplicate'); } } } $current_file = null; if ($macro->getFilePHID()) { $current_file = $macro->getFile(); } $form = new AphrontFormView(); $form->addHiddenInput('name_form', 1); $form->setUser($request->getUser()); $form->setEncType('multipart/form-data')->appendChild(id(new AphrontFormTextControl())->setLabel(pht('Name'))->setName('name')->setValue($macro->getName())->setCaption(pht('This word or phrase will be replaced with the image.'))->setError($e_name)); if (!$macro->getID()) { if ($current_file) { $current_file_view = id(new PhabricatorFileLinkView())->setFilePHID($current_file->getPHID())->setFileName($current_file->getName())->setFileViewable(true)->setFileViewURI($current_file->getBestURI())->render(); $form->addHiddenInput('phid', $current_file->getPHID()); $form->appendChild(id(new AphrontFormMarkupControl())->setLabel(pht('Selected File'))->setValue($current_file_view)); $other_label = pht('Change File'); } else { $other_label = pht('File'); } $form->appendChild(id(new AphrontFormTextControl())->setLabel(pht('URL'))->setName('url')->setValue($request->getStr('url'))->setError($request->getFileExists('file') ? false : $e_file)); $form->appendChild(id(new AphrontFormFileControl())->setLabel($other_label)->setName('file')->setError($request->getStr('url') ? false : $e_file)); } $view_uri = $this->getApplicationURI('/view/' . $macro->getID() . '/'); if ($macro->getID()) { $cancel_uri = $view_uri; } else { $cancel_uri = $this->getApplicationURI(); } $form->appendChild(id(new AphrontFormSubmitControl())->setValue(pht('Save Image Macro'))->addCancelButton($cancel_uri)); $crumbs = $this->buildApplicationCrumbs(); if ($macro->getID()) { $title = pht('Edit Image Macro'); $crumb = pht('Edit Macro'); $crumbs->addTextCrumb(pht('Macro "%s"', $macro->getName()), $view_uri); } else { $title = pht('Create Image Macro'); $crumb = pht('Create Macro'); } $crumbs->addTextCrumb($crumb, $request->getRequestURI()); $upload = null; if ($macro->getID()) { $upload_form = id(new AphrontFormView())->setEncType('multipart/form-data')->setUser($request->getUser()); $upload_form->appendChild(id(new AphrontFormTextControl())->setLabel(pht('URL'))->setName('url')->setValue($request->getStr('url'))); $upload_form->appendChild(id(new AphrontFormFileControl())->setLabel(pht('File'))->setName('file'))->appendChild(id(new AphrontFormSubmitControl())->setValue(pht('Upload File'))); $upload = id(new PHUIObjectBoxView())->setHeaderText(pht('Upload New File'))->setForm($upload_form); } $form_box = id(new PHUIObjectBoxView())->setHeaderText($title)->setFormErrors($errors)->setForm($form); return $this->buildApplicationPage(array($crumbs, $form_box, $upload), array('title' => $title)); }
public function destroyObjectPermanently(PhabricatorDestructionEngine $engine) { $this->openTransaction(); // TODO: Once this implements PhabricatorTransactionInterface, this // will be handled automatically and can be removed. $xactions = id(new ManiphestTransaction())->loadAllWhere('objectPHID = %s', $this->getPHID()); foreach ($xactions as $xaction) { $engine->destroyObject($xaction); } $this->delete(); $this->saveTransaction(); }
private function destroyTransform(PhabricatorTransformedFile $xform) { $engine = new PhabricatorDestructionEngine(); $file = id(new PhabricatorFileQuery())->setViewer($engine->getViewer())->withPHIDs(array($xform->getTransformedPHID()))->executeOne(); $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites(); if (!$file) { if ($xform->getID()) { $xform->delete(); } } else { $engine->destroyObject($file); } unset($unguarded); }
public function destroyObjectPermanently(PhabricatorDestructionEngine $engine) { $this->openTransaction(); $this->delete(); $books = id(new DivinerBookQuery())->setViewer($engine->getViewer())->withRepositoryPHIDs(array($this->getPHID()))->execute(); foreach ($books as $book) { $engine->destroyObject($book); } $atoms = id(new DivinerAtomQuery())->setViewer($engine->getViewer())->withRepositoryPHIDs(array($this->getPHID()))->execute(); foreach ($atoms as $atom) { $engine->destroyObject($atom); } $this->saveTransaction(); }
public function destroyObjectPermanently(PhabricatorDestructionEngine $engine) { $this->openTransaction(); $this->delete(); $externals = id(new PhabricatorExternalAccount())->loadAllWhere('userPHID = %s', $this->getPHID()); foreach ($externals as $external) { $external->delete(); } $prefs = id(new PhabricatorUserPreferencesQuery())->setViewer($engine->getViewer())->withUsers(array($this))->execute(); foreach ($prefs as $pref) { $engine->destroyObject($pref); } $profiles = id(new PhabricatorUserProfile())->loadAllWhere('userPHID = %s', $this->getPHID()); foreach ($profiles as $profile) { $profile->delete(); } $keys = id(new PhabricatorAuthSSHKeyQuery())->setViewer($engine->getViewer())->withObjectPHIDs(array($this->getPHID()))->execute(); foreach ($keys as $key) { $engine->destroyObject($key); } $emails = id(new PhabricatorUserEmail())->loadAllWhere('userPHID = %s', $this->getPHID()); foreach ($emails as $email) { $email->delete(); } $sessions = id(new PhabricatorAuthSession())->loadAllWhere('userPHID = %s', $this->getPHID()); foreach ($sessions as $session) { $session->delete(); } $factors = id(new PhabricatorAuthFactorConfig())->loadAllWhere('userPHID = %s', $this->getPHID()); foreach ($factors as $factor) { $factor->delete(); } $this->saveTransaction(); }