From 5704b2bc7074af540e24887d7b0a810a9a833486 Mon Sep 17 00:00:00 2001 From: epriestley Date: Mon, 11 Jul 2011 12:34:53 -0700 Subject: [PATCH] Basic edit/create workflow for Phriction Summary: This is another chunk of D636, I just simplified it a bit and added slugs. When you go to a page like /w/pokemon/, it allows you to create or edit the page. Title vs slug stuff is a little funky but I think mostly-reasonable. Test Plan: Created and edited /w/, /w/pokemon/, etc. Reviewed By: hsb Reviewers: hsb, codeblock, jungejason, aran, tuomaspelkonen CC: aran, hsb Differential Revision: 643 --- .../sql/patches/061.phrictioncontent.sql | 22 +++ src/__celerity_resource_map__.php | 9 + src/__phutil_library_map__.php | 4 + ...AphrontDefaultApplicationConfiguration.php | 4 + .../controller/base/PhrictionController.php | 2 +- .../document/PhrictionDocumentController.php | 40 ++++- .../controller/document/__init__.php | 2 + .../edit/PhrictionEditController.php | 170 ++++++++++++++++++ .../phriction/controller/edit/__init__.php | 26 +++ .../storage/content/PhrictionContent.php | 30 ++++ .../phriction/storage/content/__init__.php | 12 ++ .../phriction/phriction-document-css.css | 12 ++ 12 files changed, 329 insertions(+), 4 deletions(-) create mode 100644 resources/sql/patches/061.phrictioncontent.sql create mode 100644 src/applications/phriction/controller/edit/PhrictionEditController.php create mode 100644 src/applications/phriction/controller/edit/__init__.php create mode 100644 src/applications/phriction/storage/content/PhrictionContent.php create mode 100644 src/applications/phriction/storage/content/__init__.php create mode 100644 webroot/rsrc/css/application/phriction/phriction-document-css.css diff --git a/resources/sql/patches/061.phrictioncontent.sql b/resources/sql/patches/061.phrictioncontent.sql new file mode 100644 index 0000000000..423f05513e --- /dev/null +++ b/resources/sql/patches/061.phrictioncontent.sql @@ -0,0 +1,22 @@ +/* Patch 060 neglected to make this an AUTO_INCREMENT PRIMARY KEY */ +ALTER TABLE phabricator_phriction.phriction_document + CHANGE id id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY; + +/* Needs to be initially nullable for insert when documents are created. */ +ALTER TABLE phabricator_phriction.phriction_document + CHANGE contentID contentID INT UNSIGNED; + +CREATE TABLE phabricator_phriction.phriction_content ( + id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, + documentID INT UNSIGNED NOT NULL, + version INT UNSIGNED NOT NULL, + UNIQUE KEY (documentID, version), + authorPHID VARCHAR(64) BINARY NOT NULL, + KEY (authorPHID), + title VARCHAR(512) NOT NULL, + slug VARCHAR(512) NOT NULL, + KEY (slug), + content LONGBLOB NOT NULL, + dateCreated INT UNSIGNED NOT NULL, + dateModified INT UNSIGNED NOT NULL +) ENGINE=InnoDB; \ No newline at end of file diff --git a/src/__celerity_resource_map__.php b/src/__celerity_resource_map__.php index 54800c50f8..b638d1d94e 100644 --- a/src/__celerity_resource_map__.php +++ b/src/__celerity_resource_map__.php @@ -1135,6 +1135,15 @@ celerity_register_resource_map(array( ), 'disk' => '/rsrc/css/application/uiexample/example.css', ), + 'phriction-document-css' => + array( + 'uri' => '/res/b682cd2e/rsrc/css/application/phriction/phriction-document-css.css', + 'type' => 'css', + 'requires' => + array( + ), + 'disk' => '/rsrc/css/application/phriction/phriction-document-css.css', + ), 'syntax-highlighting-css' => array( 'uri' => '/res/e5cc3d88/rsrc/css/core/syntax.css', diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 4745a3723b..716a6a0051 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -579,10 +579,12 @@ phutil_register_library_map(array( 'PhabricatorXHProfProfileController' => 'applications/xhprof/controller/profile', 'PhabricatorXHProfProfileSymbolView' => 'applications/xhprof/view/symbol', 'PhabricatorXHProfProfileTopLevelView' => 'applications/xhprof/view/toplevel', + 'PhrictionContent' => 'applications/phriction/storage/content', 'PhrictionController' => 'applications/phriction/controller/base', 'PhrictionDAO' => 'applications/phriction/storage/base', 'PhrictionDocument' => 'applications/phriction/storage/document', 'PhrictionDocumentController' => 'applications/phriction/controller/document', + 'PhrictionEditController' => 'applications/phriction/controller/edit', ), 'function' => array( @@ -1072,10 +1074,12 @@ phutil_register_library_map(array( 'PhabricatorXHProfProfileController' => 'PhabricatorXHProfController', 'PhabricatorXHProfProfileSymbolView' => 'AphrontView', 'PhabricatorXHProfProfileTopLevelView' => 'AphrontView', + 'PhrictionContent' => 'PhrictionDAO', 'PhrictionController' => 'PhabricatorController', 'PhrictionDAO' => 'PhabricatorLiskDAO', 'PhrictionDocument' => 'PhrictionDAO', 'PhrictionDocumentController' => 'PhrictionController', + 'PhrictionEditController' => 'PhrictionController', ), 'requires_interface' => array( diff --git a/src/aphront/default/configuration/AphrontDefaultApplicationConfiguration.php b/src/aphront/default/configuration/AphrontDefaultApplicationConfiguration.php index b3c66694db..383c0ee92f 100644 --- a/src/aphront/default/configuration/AphrontDefaultApplicationConfiguration.php +++ b/src/aphront/default/configuration/AphrontDefaultApplicationConfiguration.php @@ -345,6 +345,10 @@ class AphrontDefaultApplicationConfiguration '/w(?P/)$' => 'PhrictionDocumentController', // Match "/w/x/y/z/" with slug "x/y/z/". '/w/(?P.+/)$' => 'PhrictionDocumentController', + + '/phriction/' => array( + 'edit/(?:(?P\d+)/)?$' => 'PhrictionEditController', + ), ); } diff --git a/src/applications/phriction/controller/base/PhrictionController.php b/src/applications/phriction/controller/base/PhrictionController.php index 6f2761d507..ec509e0a7a 100644 --- a/src/applications/phriction/controller/base/PhrictionController.php +++ b/src/applications/phriction/controller/base/PhrictionController.php @@ -23,7 +23,7 @@ abstract class PhrictionController extends PhabricatorController { $page = $this->buildStandardPageView(); $page->setApplicationName('Phriction'); - $page->setBaseURI('/phriction/'); + $page->setBaseURI('/w/'); $page->setTitle(idx($data, 'title')); $page->setGlyph("\xE2\x9A\xA1"); diff --git a/src/applications/phriction/controller/document/PhrictionDocumentController.php b/src/applications/phriction/controller/document/PhrictionDocumentController.php index 46176fba37..f9110a5424 100644 --- a/src/applications/phriction/controller/document/PhrictionDocumentController.php +++ b/src/applications/phriction/controller/document/PhrictionDocumentController.php @@ -34,12 +34,46 @@ class PhrictionDocumentController return id(new AphrontRedirectResponse())->setURI($uri); } - $slug_info = 'Phriction page for '.phutil_escape_html($this->slug); + require_celerity_resource('phriction-document-css'); + + $document = id(new PhrictionDocument())->loadOneWhere( + 'slug = %s', + $slug); + + if (!$document) { + $page_content = 'No content here!'; + $page_title = 'Page Not Found'; + $button = phutil_render_tag( + 'a', + array( + 'href' => '/phriction/edit/?slug='.$slug, + 'class' => 'green button', + ), + 'Create Page'); + } else { + $content = id(new PhrictionContent())->load($document->getContentID()); + $page_content = phutil_escape_html($content->getContent()); + $page_title = $content->getTitle(); + $button = phutil_render_tag( + 'a', + array( + 'href' => '/phriction/edit/'.$document->getID().'/', + 'class' => 'button', + ), + 'Edit Page'); + } + + $page = + '
'. + $button. + '

'.phutil_escape_html($page_title).'

'. + '
'. + $page_content; return $this->buildStandardPageResponse( - $slug_info, + $page, array( - 'title' => 'Phriction', + 'title' => 'Phriction - '.$page_title, )); } diff --git a/src/applications/phriction/controller/document/__init__.php b/src/applications/phriction/controller/document/__init__.php index 3bccce34b6..10fdba038d 100644 --- a/src/applications/phriction/controller/document/__init__.php +++ b/src/applications/phriction/controller/document/__init__.php @@ -8,7 +8,9 @@ phutil_require_module('phabricator', 'aphront/response/redirect'); phutil_require_module('phabricator', 'applications/phriction/controller/base'); +phutil_require_module('phabricator', 'applications/phriction/storage/content'); phutil_require_module('phabricator', 'applications/phriction/storage/document'); +phutil_require_module('phabricator', 'infrastructure/celerity/api'); phutil_require_module('phutil', 'markup'); phutil_require_module('phutil', 'utils'); diff --git a/src/applications/phriction/controller/edit/PhrictionEditController.php b/src/applications/phriction/controller/edit/PhrictionEditController.php new file mode 100644 index 0000000000..645cd9a08c --- /dev/null +++ b/src/applications/phriction/controller/edit/PhrictionEditController.php @@ -0,0 +1,170 @@ +id = idx($data, 'id'); + } + + public function processRequest() { + + $request = $this->getRequest(); + $user = $request->getUser(); + + $slug = $request->getStr('slug'); + $slug = PhrictionDocument::normalizeSlug($slug); + + if ($this->id) { + $document = id(new PhrictionDocument())->load($this->id); + if (!$document) { + return new Aphront404Response(); + } + $content = id(new PhrictionContent())->load($document->getContentID()); + } else if ($slug) { + $document = null; + if ($slug) { + $document = id(new PhrictionDocument())->loadOneWhere( + 'slug = %s', + $slug); + } + + if ($document) { + $content = id(new PhrictionContent())->load($document->getContentID()); + } else { + $document = new PhrictionDocument(); + $document->setSlug($slug); + + $content = new PhrictionContent(); + $content->setSlug($slug); + + $default_title = null; + if ($slug) { + $default_title = end(explode('/', trim($slug, '/'))); + $default_title = str_replace('_', ' ', $default_title); + $default_title = ucwords($default_title); + } + $default_title = nonempty($default_title, 'New Document'); + $content->setTitle($default_title); + } + } else { + return new Aphront404Response(); + } + + $e_title = true; + $errors = array(); + + if ($request->isFormPost()) { + $title = $request->getStr('title'); + + if (!strlen($title)) { + $e_title = 'Required'; + $errors[] = 'Document title is required.'; + } else { + $e_title = null; + } + + if (!count($errors)) { + + // TODO: This should all be transactional. + + if (!$document->getID()) { + $document->save(); + } + + $new_content = new PhrictionContent(); + $new_content->setSlug($document->getSlug()); + $new_content->setTitle($title); + $new_content->setContent($request->getStr('content')); + + $new_content->setDocumentID($document->getID()); + $new_content->setVersion($content->getVersion() + 1); + + $new_content->setAuthorPHID($user->getPHID()); + $new_content->save(); + + $document->setContentID($new_content->getID()); + $document->save(); + + $uri = PhrictionDocument::getSlugURI($document->getSlug()); + return id(new AphrontRedirectResponse())->setURI($uri); + } + } + + $error_view = null; + if ($errors) { + $error_view = id(new AphrontErrorView()) + ->setTitle('Form Errors') + ->setErrors($errors); + } + + if ($document->getID()) { + $panel_header = 'Edit Phriction Document'; + $submit_button = 'Edit Document'; + } else { + $panel_header = 'Create New Phriction Document'; + $submit_button = 'Create Document'; + } + + $uri = $document->getSlug(); + $uri = PhrictionDocument::getSlugURI($uri); + $uri = PhabricatorEnv::getProductionURI($uri); + + $form = id(new AphrontFormView()) + ->setUser($user) + ->setAction($request->getRequestURI()->getPath()) + ->addHiddenInput('slug', $slug) + ->appendChild( + id(new AphrontFormTextControl()) + ->setLabel('Title') + ->setValue($content->getTitle()) + ->setError($e_title) + ->setName('title')) + ->appendChild( + id(new AphrontFormStaticControl()) + ->setLabel('URI') + ->setValue($uri)) + ->appendChild( + id(new AphrontFormTextAreaControl()) + ->setLabel('Content') + ->setValue($content->getContent()) + ->setHeight(AphrontFormTextAreaControl::HEIGHT_VERY_TALL) + ->setName('content')) + ->appendChild( + id(new AphrontFormSubmitControl()) + ->setValue($submit_button)); + + $panel = id(new AphrontPanelView()) + ->setWidth(AphrontPanelView::WIDTH_WIDE) + ->setHeader($panel_header) + ->appendChild($form); + + return $this->buildStandardPageResponse( + array( + $error_view, + $panel, + ), + array( + 'title' => 'Edit Document', + )); + } + +} diff --git a/src/applications/phriction/controller/edit/__init__.php b/src/applications/phriction/controller/edit/__init__.php new file mode 100644 index 0000000000..8c9ca92237 --- /dev/null +++ b/src/applications/phriction/controller/edit/__init__.php @@ -0,0 +1,26 @@ +