mirror of
https://we.phorge.it/source/phorge.git
synced 2025-02-17 01:08:41 +01:00
Adding Ponder-related files.
Summary: Ponder is similar in spirit to the Wiki tool, but uses a Q&A format and up/downvotes to signal user sentiment. Popular questions are moved to the top of the feed on a 5-minute cycle based on age (younger is better) and vote count (higher is better). Pre-apologies for noob diff. Test Plan: - `./bin/phd list` Should include `PonderHeatDaemon`; phd launch it if necessary. - Navigate to /ponder/ ; observe sanity when adding questions, voting on them, and adding answers. - Confirm that questions and answers are linkable using Q5 / Q5#A5 formatted object links. - Confirm that searching for Ponder Questions works using built-in search. Feedback on code / schema / whatever organization very welcome. Reviewers: nh, vrana, epriestley Reviewed By: epriestley CC: gmarcotte, aran, Korvin, starruler Differential Revision: https://secure.phabricator.com/D3136
This commit is contained in:
parent
9030fe8b09
commit
64472dd7b8
50 changed files with 3204 additions and 51 deletions
50
resources/sql/patches/ponder.sql
Normal file
50
resources/sql/patches/ponder.sql
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
CREATE TABLE `{$NAMESPACE}_ponder`.`ponder_question` (
|
||||||
|
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`title` varchar(255) NOT NULL,
|
||||||
|
`phid` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
|
||||||
|
`voteCount` int(10) NOT NULL,
|
||||||
|
`authorPHID` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
|
||||||
|
`content` longtext CHARACTER SET utf8 NOT NULL,
|
||||||
|
`dateCreated` int(10) unsigned NOT NULL,
|
||||||
|
`dateModified` int(10) unsigned NOT NULL,
|
||||||
|
`contentSource` varchar(255) DEFAULT NULL,
|
||||||
|
`heat` float NOT NULL,
|
||||||
|
`answerCount` int(10) unsigned NOT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
UNIQUE KEY `phid` (`phid`),
|
||||||
|
KEY `authorPHID` (`authorPHID`),
|
||||||
|
KEY `heat` (`heat`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
CREATE TABLE `{$NAMESPACE}_ponder`.`ponder_answer` (
|
||||||
|
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`questionID` int(10) unsigned NOT NULL,
|
||||||
|
`phid` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
|
||||||
|
`voteCount` int(10) NOT NULL,
|
||||||
|
`authorPHID` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
|
||||||
|
`content` longtext CHARACTER SET utf8 NOT NULL,
|
||||||
|
`dateCreated` int(10) unsigned NOT NULL,
|
||||||
|
`dateModified` int(10) unsigned NOT NULL,
|
||||||
|
`contentSource` varchar(255) DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
UNIQUE KEY `phid` (`phid`),
|
||||||
|
KEY `questionID` (`questionID`),
|
||||||
|
KEY `authorPHID` (`authorPHID`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
CREATE TABLE `{$NAMESPACE}_ponder`.`edge` (
|
||||||
|
`src` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
|
||||||
|
`type` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
|
||||||
|
`dst` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
|
||||||
|
`dateCreated` int(10) unsigned NOT NULL,
|
||||||
|
`seq` int(10) unsigned NOT NULL,
|
||||||
|
`dataID` int(10) unsigned DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`src`,`type`,`dst`),
|
||||||
|
KEY `src` (`src`,`type`,`dateCreated`,`seq`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
CREATE TABLE `{$NAMESPACE}_ponder`.`edgedata` (
|
||||||
|
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`data` longtext CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
|
@ -63,6 +63,13 @@ celerity_register_resource_map(array(
|
||||||
'disk' => '/rsrc/image/app/app_phriction.png',
|
'disk' => '/rsrc/image/app/app_phriction.png',
|
||||||
'type' => 'png',
|
'type' => 'png',
|
||||||
),
|
),
|
||||||
|
'/rsrc/image/app/app_ponder.png' =>
|
||||||
|
array(
|
||||||
|
'hash' => '9893ca3674af96884d3564ecbe101280',
|
||||||
|
'uri' => '/res/9893ca36/rsrc/image/app/app_ponder.png',
|
||||||
|
'disk' => '/rsrc/image/app/app_ponder.png',
|
||||||
|
'type' => 'png',
|
||||||
|
),
|
||||||
'/rsrc/image/app/app_settings.png' =>
|
'/rsrc/image/app/app_settings.png' =>
|
||||||
array(
|
array(
|
||||||
'hash' => '095fa0e61ec11d3f7e543ba48f5a5adb',
|
'hash' => '095fa0e61ec11d3f7e543ba48f5a5adb',
|
||||||
|
@ -70,10 +77,24 @@ celerity_register_resource_map(array(
|
||||||
'disk' => '/rsrc/image/app/app_settings.png',
|
'disk' => '/rsrc/image/app/app_settings.png',
|
||||||
'type' => 'png',
|
'type' => 'png',
|
||||||
),
|
),
|
||||||
|
'/rsrc/image/application/ponder/downvote.png' =>
|
||||||
|
array(
|
||||||
|
'hash' => '46c5644a0fccb9e237a3363e07f50487',
|
||||||
|
'uri' => '/res/46c5644a/rsrc/image/application/ponder/downvote.png',
|
||||||
|
'disk' => '/rsrc/image/application/ponder/downvote.png',
|
||||||
|
'type' => 'png',
|
||||||
|
),
|
||||||
|
'/rsrc/image/application/ponder/upvote.png' =>
|
||||||
|
array(
|
||||||
|
'hash' => 'edd58ed3a09f3017c78601b1a5d0e7a7',
|
||||||
|
'uri' => '/res/edd58ed3/rsrc/image/application/ponder/upvote.png',
|
||||||
|
'disk' => '/rsrc/image/application/ponder/upvote.png',
|
||||||
|
'type' => 'png',
|
||||||
|
),
|
||||||
'/rsrc/image/apps.png' =>
|
'/rsrc/image/apps.png' =>
|
||||||
array(
|
array(
|
||||||
'hash' => 'f7cb4abeb73245fea4098a02fd784653',
|
'hash' => '134f6ac3d63e24070bf7a11b294ca72c',
|
||||||
'uri' => '/res/f7cb4abe/rsrc/image/apps.png',
|
'uri' => '/res/134f6ac3/rsrc/image/apps.png',
|
||||||
'disk' => '/rsrc/image/apps.png',
|
'disk' => '/rsrc/image/apps.png',
|
||||||
'type' => 'png',
|
'type' => 'png',
|
||||||
),
|
),
|
||||||
|
@ -1608,6 +1629,32 @@ celerity_register_resource_map(array(
|
||||||
),
|
),
|
||||||
'disk' => '/rsrc/js/application/phriction/phriction-document-preview.js',
|
'disk' => '/rsrc/js/application/phriction/phriction-document-preview.js',
|
||||||
),
|
),
|
||||||
|
'javelin-behavior-ponder-feedback-preview' =>
|
||||||
|
array(
|
||||||
|
'uri' => '/res/2e802dd9/rsrc/js/application/ponder/behavior-comment-preview.js',
|
||||||
|
'type' => 'js',
|
||||||
|
'requires' =>
|
||||||
|
array(
|
||||||
|
0 => 'javelin-behavior',
|
||||||
|
1 => 'javelin-dom',
|
||||||
|
2 => 'javelin-util',
|
||||||
|
3 => 'phabricator-shaped-request',
|
||||||
|
),
|
||||||
|
'disk' => '/rsrc/js/application/ponder/behavior-comment-preview.js',
|
||||||
|
),
|
||||||
|
'javelin-behavior-ponder-votebox' =>
|
||||||
|
array(
|
||||||
|
'uri' => '/res/6517d3f5/rsrc/js/application/ponder/behavior-votebox.js',
|
||||||
|
'type' => 'js',
|
||||||
|
'requires' =>
|
||||||
|
array(
|
||||||
|
0 => 'javelin-behavior',
|
||||||
|
1 => 'javelin-dom',
|
||||||
|
2 => 'javelin-util',
|
||||||
|
3 => 'phabricator-shaped-request',
|
||||||
|
),
|
||||||
|
'disk' => '/rsrc/js/application/ponder/behavior-votebox.js',
|
||||||
|
),
|
||||||
'javelin-behavior-project-create' =>
|
'javelin-behavior-project-create' =>
|
||||||
array(
|
array(
|
||||||
'uri' => '/res/e91f3f8f/rsrc/js/application/projects/behavior-project-create.js',
|
'uri' => '/res/e91f3f8f/rsrc/js/application/projects/behavior-project-create.js',
|
||||||
|
@ -1635,7 +1682,7 @@ celerity_register_resource_map(array(
|
||||||
),
|
),
|
||||||
'javelin-behavior-repository-crossreference' =>
|
'javelin-behavior-repository-crossreference' =>
|
||||||
array(
|
array(
|
||||||
'uri' => '/res/e0d58d3b/rsrc/js/application/repository/repository-crossreference.js',
|
'uri' => '/res/12700384/rsrc/js/application/repository/repository-crossreference.js',
|
||||||
'type' => 'js',
|
'type' => 'js',
|
||||||
'requires' =>
|
'requires' =>
|
||||||
array(
|
array(
|
||||||
|
@ -2200,7 +2247,7 @@ celerity_register_resource_map(array(
|
||||||
),
|
),
|
||||||
'phabricator-app-buttons-css' =>
|
'phabricator-app-buttons-css' =>
|
||||||
array(
|
array(
|
||||||
'uri' => '/res/1e153463/rsrc/css/application/directory/phabricator-app-buttons.css',
|
'uri' => '/res/2d5d414c/rsrc/css/application/directory/phabricator-app-buttons.css',
|
||||||
'type' => 'css',
|
'type' => 'css',
|
||||||
'requires' =>
|
'requires' =>
|
||||||
array(
|
array(
|
||||||
|
@ -2730,6 +2777,42 @@ celerity_register_resource_map(array(
|
||||||
),
|
),
|
||||||
'disk' => '/rsrc/css/application/phriction/phriction-document-css.css',
|
'disk' => '/rsrc/css/application/phriction/phriction-document-css.css',
|
||||||
),
|
),
|
||||||
|
'ponder-core-view-css' =>
|
||||||
|
array(
|
||||||
|
'uri' => '/res/4a6e2fc7/rsrc/css/application/ponder/core.css',
|
||||||
|
'type' => 'css',
|
||||||
|
'requires' =>
|
||||||
|
array(
|
||||||
|
),
|
||||||
|
'disk' => '/rsrc/css/application/ponder/core.css',
|
||||||
|
),
|
||||||
|
'ponder-feed-view-css' =>
|
||||||
|
array(
|
||||||
|
'uri' => '/res/df22bd20/rsrc/css/application/ponder/feed.css',
|
||||||
|
'type' => 'css',
|
||||||
|
'requires' =>
|
||||||
|
array(
|
||||||
|
),
|
||||||
|
'disk' => '/rsrc/css/application/ponder/feed.css',
|
||||||
|
),
|
||||||
|
'ponder-post-css' =>
|
||||||
|
array(
|
||||||
|
'uri' => '/res/32c960df/rsrc/css/application/ponder/post.css',
|
||||||
|
'type' => 'css',
|
||||||
|
'requires' =>
|
||||||
|
array(
|
||||||
|
),
|
||||||
|
'disk' => '/rsrc/css/application/ponder/post.css',
|
||||||
|
),
|
||||||
|
'ponder-vote-css' =>
|
||||||
|
array(
|
||||||
|
'uri' => '/res/923bcf97/rsrc/css/application/ponder/vote.css',
|
||||||
|
'type' => 'css',
|
||||||
|
'requires' =>
|
||||||
|
array(
|
||||||
|
),
|
||||||
|
'disk' => '/rsrc/css/application/ponder/vote.css',
|
||||||
|
),
|
||||||
'raphael-core' =>
|
'raphael-core' =>
|
||||||
array(
|
array(
|
||||||
'uri' => '/res/3f48575a/rsrc/js/raphael/raphael.js',
|
'uri' => '/res/3f48575a/rsrc/js/raphael/raphael.js',
|
||||||
|
@ -2777,7 +2860,7 @@ celerity_register_resource_map(array(
|
||||||
),
|
),
|
||||||
'syntax-highlighting-css' =>
|
'syntax-highlighting-css' =>
|
||||||
array(
|
array(
|
||||||
'uri' => '/res/5669beb6/rsrc/css/core/syntax.css',
|
'uri' => '/res/cb3b9dc0/rsrc/css/core/syntax.css',
|
||||||
'type' => 'css',
|
'type' => 'css',
|
||||||
'requires' =>
|
'requires' =>
|
||||||
array(
|
array(
|
||||||
|
@ -2787,7 +2870,7 @@ celerity_register_resource_map(array(
|
||||||
), array(
|
), array(
|
||||||
'packages' =>
|
'packages' =>
|
||||||
array(
|
array(
|
||||||
'8b65e80d' =>
|
'04e1ab3e' =>
|
||||||
array(
|
array(
|
||||||
'name' => 'core.pkg.css',
|
'name' => 'core.pkg.css',
|
||||||
'symbols' =>
|
'symbols' =>
|
||||||
|
@ -2816,7 +2899,7 @@ celerity_register_resource_map(array(
|
||||||
21 => 'phabricator-flag-css',
|
21 => 'phabricator-flag-css',
|
||||||
22 => 'aphront-error-view-css',
|
22 => 'aphront-error-view-css',
|
||||||
),
|
),
|
||||||
'uri' => '/res/pkg/8b65e80d/core.pkg.css',
|
'uri' => '/res/pkg/04e1ab3e/core.pkg.css',
|
||||||
'type' => 'css',
|
'type' => 'css',
|
||||||
),
|
),
|
||||||
'971b021e' =>
|
'971b021e' =>
|
||||||
|
@ -2867,7 +2950,7 @@ celerity_register_resource_map(array(
|
||||||
'uri' => '/res/pkg/96bc37d6/differential.pkg.css',
|
'uri' => '/res/pkg/96bc37d6/differential.pkg.css',
|
||||||
'type' => 'css',
|
'type' => 'css',
|
||||||
),
|
),
|
||||||
'ace0431a' =>
|
93479628 =>
|
||||||
array(
|
array(
|
||||||
'name' => 'differential.pkg.js',
|
'name' => 'differential.pkg.js',
|
||||||
'symbols' =>
|
'symbols' =>
|
||||||
|
@ -2891,7 +2974,7 @@ celerity_register_resource_map(array(
|
||||||
16 => 'javelin-behavior-differential-dropdown-menus',
|
16 => 'javelin-behavior-differential-dropdown-menus',
|
||||||
17 => 'javelin-behavior-buoyant',
|
17 => 'javelin-behavior-buoyant',
|
||||||
),
|
),
|
||||||
'uri' => '/res/pkg/ace0431a/differential.pkg.js',
|
'uri' => '/res/pkg/93479628/differential.pkg.js',
|
||||||
'type' => 'js',
|
'type' => 'js',
|
||||||
),
|
),
|
||||||
'c8ce2d88' =>
|
'c8ce2d88' =>
|
||||||
|
@ -2983,23 +3066,23 @@ celerity_register_resource_map(array(
|
||||||
'reverse' =>
|
'reverse' =>
|
||||||
array(
|
array(
|
||||||
'aphront-attached-file-view-css' => '7839ae2d',
|
'aphront-attached-file-view-css' => '7839ae2d',
|
||||||
'aphront-crumbs-view-css' => '8b65e80d',
|
'aphront-crumbs-view-css' => '04e1ab3e',
|
||||||
'aphront-dialog-view-css' => '8b65e80d',
|
'aphront-dialog-view-css' => '04e1ab3e',
|
||||||
'aphront-error-view-css' => '8b65e80d',
|
'aphront-error-view-css' => '04e1ab3e',
|
||||||
'aphront-form-view-css' => '8b65e80d',
|
'aphront-form-view-css' => '04e1ab3e',
|
||||||
'aphront-headsup-action-list-view-css' => '96bc37d6',
|
'aphront-headsup-action-list-view-css' => '96bc37d6',
|
||||||
'aphront-headsup-view-css' => '8b65e80d',
|
'aphront-headsup-view-css' => '04e1ab3e',
|
||||||
'aphront-list-filter-view-css' => '8b65e80d',
|
'aphront-list-filter-view-css' => '04e1ab3e',
|
||||||
'aphront-pager-view-css' => '8b65e80d',
|
'aphront-pager-view-css' => '04e1ab3e',
|
||||||
'aphront-panel-view-css' => '8b65e80d',
|
'aphront-panel-view-css' => '04e1ab3e',
|
||||||
'aphront-side-nav-view-css' => '8b65e80d',
|
'aphront-side-nav-view-css' => '04e1ab3e',
|
||||||
'aphront-table-view-css' => '8b65e80d',
|
'aphront-table-view-css' => '04e1ab3e',
|
||||||
'aphront-tokenizer-control-css' => '8b65e80d',
|
'aphront-tokenizer-control-css' => '04e1ab3e',
|
||||||
'aphront-tooltip-css' => '8b65e80d',
|
'aphront-tooltip-css' => '04e1ab3e',
|
||||||
'aphront-typeahead-control-css' => '8b65e80d',
|
'aphront-typeahead-control-css' => '04e1ab3e',
|
||||||
'differential-changeset-view-css' => '96bc37d6',
|
'differential-changeset-view-css' => '96bc37d6',
|
||||||
'differential-core-view-css' => '96bc37d6',
|
'differential-core-view-css' => '96bc37d6',
|
||||||
'differential-inline-comment-editor' => 'ace0431a',
|
'differential-inline-comment-editor' => '93479628',
|
||||||
'differential-local-commits-view-css' => '96bc37d6',
|
'differential-local-commits-view-css' => '96bc37d6',
|
||||||
'differential-results-table-css' => '96bc37d6',
|
'differential-results-table-css' => '96bc37d6',
|
||||||
'differential-revision-add-comment-css' => '96bc37d6',
|
'differential-revision-add-comment-css' => '96bc37d6',
|
||||||
|
@ -3012,21 +3095,21 @@ celerity_register_resource_map(array(
|
||||||
'inline-comment-summary-css' => '96bc37d6',
|
'inline-comment-summary-css' => '96bc37d6',
|
||||||
'javelin-behavior' => '6fb20113',
|
'javelin-behavior' => '6fb20113',
|
||||||
'javelin-behavior-aphront-basic-tokenizer' => '97f65640',
|
'javelin-behavior-aphront-basic-tokenizer' => '97f65640',
|
||||||
'javelin-behavior-aphront-drag-and-drop' => 'ace0431a',
|
'javelin-behavior-aphront-drag-and-drop' => '93479628',
|
||||||
'javelin-behavior-aphront-drag-and-drop-textarea' => 'ace0431a',
|
'javelin-behavior-aphront-drag-and-drop-textarea' => '93479628',
|
||||||
'javelin-behavior-aphront-form-disable-on-submit' => '971b021e',
|
'javelin-behavior-aphront-form-disable-on-submit' => '971b021e',
|
||||||
'javelin-behavior-audit-preview' => '5e68be89',
|
'javelin-behavior-audit-preview' => '5e68be89',
|
||||||
'javelin-behavior-buoyant' => 'ace0431a',
|
'javelin-behavior-buoyant' => '93479628',
|
||||||
'javelin-behavior-differential-accept-with-errors' => 'ace0431a',
|
'javelin-behavior-differential-accept-with-errors' => '93479628',
|
||||||
'javelin-behavior-differential-add-reviewers-and-ccs' => 'ace0431a',
|
'javelin-behavior-differential-add-reviewers-and-ccs' => '93479628',
|
||||||
'javelin-behavior-differential-comment-jump' => 'ace0431a',
|
'javelin-behavior-differential-comment-jump' => '93479628',
|
||||||
'javelin-behavior-differential-diff-radios' => 'ace0431a',
|
'javelin-behavior-differential-diff-radios' => '93479628',
|
||||||
'javelin-behavior-differential-dropdown-menus' => 'ace0431a',
|
'javelin-behavior-differential-dropdown-menus' => '93479628',
|
||||||
'javelin-behavior-differential-edit-inline-comments' => 'ace0431a',
|
'javelin-behavior-differential-edit-inline-comments' => '93479628',
|
||||||
'javelin-behavior-differential-feedback-preview' => 'ace0431a',
|
'javelin-behavior-differential-feedback-preview' => '93479628',
|
||||||
'javelin-behavior-differential-keyboard-navigation' => 'ace0431a',
|
'javelin-behavior-differential-keyboard-navigation' => '93479628',
|
||||||
'javelin-behavior-differential-populate' => 'ace0431a',
|
'javelin-behavior-differential-populate' => '93479628',
|
||||||
'javelin-behavior-differential-show-more' => 'ace0431a',
|
'javelin-behavior-differential-show-more' => '93479628',
|
||||||
'javelin-behavior-diffusion-commit-graph' => '5e68be89',
|
'javelin-behavior-diffusion-commit-graph' => '5e68be89',
|
||||||
'javelin-behavior-diffusion-pull-lastmodified' => '5e68be89',
|
'javelin-behavior-diffusion-pull-lastmodified' => '5e68be89',
|
||||||
'javelin-behavior-maniphest-batch-selector' => '7707de41',
|
'javelin-behavior-maniphest-batch-selector' => '7707de41',
|
||||||
|
@ -3036,12 +3119,12 @@ celerity_register_resource_map(array(
|
||||||
'javelin-behavior-maniphest-transaction-preview' => '7707de41',
|
'javelin-behavior-maniphest-transaction-preview' => '7707de41',
|
||||||
'javelin-behavior-phabricator-autofocus' => '971b021e',
|
'javelin-behavior-phabricator-autofocus' => '971b021e',
|
||||||
'javelin-behavior-phabricator-keyboard-shortcuts' => '971b021e',
|
'javelin-behavior-phabricator-keyboard-shortcuts' => '971b021e',
|
||||||
'javelin-behavior-phabricator-object-selector' => 'ace0431a',
|
'javelin-behavior-phabricator-object-selector' => '93479628',
|
||||||
'javelin-behavior-phabricator-oncopy' => '971b021e',
|
'javelin-behavior-phabricator-oncopy' => '971b021e',
|
||||||
'javelin-behavior-phabricator-tooltips' => '971b021e',
|
'javelin-behavior-phabricator-tooltips' => '971b021e',
|
||||||
'javelin-behavior-phabricator-watch-anchor' => '971b021e',
|
'javelin-behavior-phabricator-watch-anchor' => '971b021e',
|
||||||
'javelin-behavior-refresh-csrf' => '971b021e',
|
'javelin-behavior-refresh-csrf' => '971b021e',
|
||||||
'javelin-behavior-repository-crossreference' => 'ace0431a',
|
'javelin-behavior-repository-crossreference' => '93479628',
|
||||||
'javelin-behavior-workflow' => '971b021e',
|
'javelin-behavior-workflow' => '971b021e',
|
||||||
'javelin-dom' => '6fb20113',
|
'javelin-dom' => '6fb20113',
|
||||||
'javelin-event' => '6fb20113',
|
'javelin-event' => '6fb20113',
|
||||||
|
@ -3062,15 +3145,15 @@ celerity_register_resource_map(array(
|
||||||
'javelin-workflow' => '971b021e',
|
'javelin-workflow' => '971b021e',
|
||||||
'maniphest-task-summary-css' => '7839ae2d',
|
'maniphest-task-summary-css' => '7839ae2d',
|
||||||
'maniphest-transaction-detail-css' => '7839ae2d',
|
'maniphest-transaction-detail-css' => '7839ae2d',
|
||||||
'phabricator-app-buttons-css' => '8b65e80d',
|
'phabricator-app-buttons-css' => '04e1ab3e',
|
||||||
'phabricator-content-source-view-css' => '96bc37d6',
|
'phabricator-content-source-view-css' => '96bc37d6',
|
||||||
'phabricator-core-buttons-css' => '8b65e80d',
|
'phabricator-core-buttons-css' => '04e1ab3e',
|
||||||
'phabricator-core-css' => '8b65e80d',
|
'phabricator-core-css' => '04e1ab3e',
|
||||||
'phabricator-directory-css' => '8b65e80d',
|
'phabricator-directory-css' => '04e1ab3e',
|
||||||
'phabricator-drag-and-drop-file-upload' => 'ace0431a',
|
'phabricator-drag-and-drop-file-upload' => '93479628',
|
||||||
'phabricator-dropdown-menu' => '971b021e',
|
'phabricator-dropdown-menu' => '971b021e',
|
||||||
'phabricator-flag-css' => '8b65e80d',
|
'phabricator-flag-css' => '04e1ab3e',
|
||||||
'phabricator-jump-nav' => '8b65e80d',
|
'phabricator-jump-nav' => '04e1ab3e',
|
||||||
'phabricator-keyboard-shortcut' => '971b021e',
|
'phabricator-keyboard-shortcut' => '971b021e',
|
||||||
'phabricator-keyboard-shortcut-manager' => '971b021e',
|
'phabricator-keyboard-shortcut-manager' => '971b021e',
|
||||||
'phabricator-menu-item' => '971b021e',
|
'phabricator-menu-item' => '971b021e',
|
||||||
|
@ -3078,11 +3161,11 @@ celerity_register_resource_map(array(
|
||||||
'phabricator-paste-file-upload' => '971b021e',
|
'phabricator-paste-file-upload' => '971b021e',
|
||||||
'phabricator-prefab' => '971b021e',
|
'phabricator-prefab' => '971b021e',
|
||||||
'phabricator-project-tag-css' => '7839ae2d',
|
'phabricator-project-tag-css' => '7839ae2d',
|
||||||
'phabricator-remarkup-css' => '8b65e80d',
|
'phabricator-remarkup-css' => '04e1ab3e',
|
||||||
'phabricator-shaped-request' => 'ace0431a',
|
'phabricator-shaped-request' => '93479628',
|
||||||
'phabricator-standard-page-view' => '8b65e80d',
|
'phabricator-standard-page-view' => '04e1ab3e',
|
||||||
'phabricator-tooltip' => '971b021e',
|
'phabricator-tooltip' => '971b021e',
|
||||||
'phabricator-transaction-view-css' => '8b65e80d',
|
'phabricator-transaction-view-css' => '04e1ab3e',
|
||||||
'syntax-highlighting-css' => '8b65e80d',
|
'syntax-highlighting-css' => '04e1ab3e',
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
|
|
|
@ -554,6 +554,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorApplicationManiphest' => 'applications/maniphest/application/PhabricatorApplicationManiphest.php',
|
'PhabricatorApplicationManiphest' => 'applications/maniphest/application/PhabricatorApplicationManiphest.php',
|
||||||
'PhabricatorApplicationPeople' => 'applications/people/application/PhabricatorApplicationPeople.php',
|
'PhabricatorApplicationPeople' => 'applications/people/application/PhabricatorApplicationPeople.php',
|
||||||
'PhabricatorApplicationPhriction' => 'applications/phriction/application/PhabricatorApplicationPhriction.php',
|
'PhabricatorApplicationPhriction' => 'applications/phriction/application/PhabricatorApplicationPhriction.php',
|
||||||
|
'PhabricatorApplicationPonder' => 'applications/ponder/application/PhabricatorApplicationPonder.php',
|
||||||
'PhabricatorApplicationProject' => 'applications/project/application/PhabricatorApplicationProject.php',
|
'PhabricatorApplicationProject' => 'applications/project/application/PhabricatorApplicationProject.php',
|
||||||
'PhabricatorApplicationSettings' => 'applications/people/application/PhabricatorApplicationSettings.php',
|
'PhabricatorApplicationSettings' => 'applications/people/application/PhabricatorApplicationSettings.php',
|
||||||
'PhabricatorApplicationStatusView' => 'applications/meta/view/PhabricatorApplicationStatusView.php',
|
'PhabricatorApplicationStatusView' => 'applications/meta/view/PhabricatorApplicationStatusView.php',
|
||||||
|
@ -990,6 +991,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorSearchIndexController' => 'applications/search/controller/PhabricatorSearchIndexController.php',
|
'PhabricatorSearchIndexController' => 'applications/search/controller/PhabricatorSearchIndexController.php',
|
||||||
'PhabricatorSearchManiphestIndexer' => 'applications/search/index/indexer/PhabricatorSearchManiphestIndexer.php',
|
'PhabricatorSearchManiphestIndexer' => 'applications/search/index/indexer/PhabricatorSearchManiphestIndexer.php',
|
||||||
'PhabricatorSearchPhrictionIndexer' => 'applications/search/index/indexer/PhabricatorSearchPhrictionIndexer.php',
|
'PhabricatorSearchPhrictionIndexer' => 'applications/search/index/indexer/PhabricatorSearchPhrictionIndexer.php',
|
||||||
|
'PhabricatorSearchPonderIndexer' => 'applications/ponder/search/PhabricatorSearchPonderIndexer.php',
|
||||||
'PhabricatorSearchQuery' => 'applications/search/storage/PhabricatorSearchQuery.php',
|
'PhabricatorSearchQuery' => 'applications/search/storage/PhabricatorSearchQuery.php',
|
||||||
'PhabricatorSearchRelationship' => 'applications/search/constants/PhabricatorSearchRelationship.php',
|
'PhabricatorSearchRelationship' => 'applications/search/constants/PhabricatorSearchRelationship.php',
|
||||||
'PhabricatorSearchResultView' => 'applications/search/view/PhabricatorSearchResultView.php',
|
'PhabricatorSearchResultView' => 'applications/search/view/PhabricatorSearchResultView.php',
|
||||||
|
@ -1137,6 +1139,34 @@ phutil_register_library_map(array(
|
||||||
'PhrictionEditController' => 'applications/phriction/controller/PhrictionEditController.php',
|
'PhrictionEditController' => 'applications/phriction/controller/PhrictionEditController.php',
|
||||||
'PhrictionHistoryController' => 'applications/phriction/controller/PhrictionHistoryController.php',
|
'PhrictionHistoryController' => 'applications/phriction/controller/PhrictionHistoryController.php',
|
||||||
'PhrictionListController' => 'applications/phriction/controller/PhrictionListController.php',
|
'PhrictionListController' => 'applications/phriction/controller/PhrictionListController.php',
|
||||||
|
'PonderAddAnswerView' => 'applications/ponder/view/PonderAddAnswerView.php',
|
||||||
|
'PonderAnswer' => 'applications/ponder/storage/PonderAnswer.php',
|
||||||
|
'PonderAnswerEditor' => 'applications/ponder/editor/PonderAnswerEditor.php',
|
||||||
|
'PonderAnswerListView' => 'applications/ponder/view/PonderAnswerListView.php',
|
||||||
|
'PonderAnswerPreviewController' => 'applications/ponder/controller/PonderAnswerPreviewController.php',
|
||||||
|
'PonderAnswerQuery' => 'applications/ponder/query/PonderAnswerQuery.php',
|
||||||
|
'PonderAnswerSaveController' => 'applications/ponder/controller/PonderAnswerSaveController.php',
|
||||||
|
'PonderAnswerSummaryView' => 'applications/ponder/view/PonderAnswerSummaryView.php',
|
||||||
|
'PonderAnswerViewController' => 'applications/ponder/controller/PonderAnswerViewController.php',
|
||||||
|
'PonderCommentBodyView' => 'applications/ponder/view/PonderCommentBodyView.php',
|
||||||
|
'PonderConstants' => 'applications/ponder/PonderConstants.php',
|
||||||
|
'PonderController' => 'applications/ponder/controller/PonderController.php',
|
||||||
|
'PonderDAO' => 'applications/ponder/storage/PonderDAO.php',
|
||||||
|
'PonderFeedController' => 'applications/ponder/controller/PonderFeedController.php',
|
||||||
|
'PonderQuestion' => 'applications/ponder/storage/PonderQuestion.php',
|
||||||
|
'PonderQuestionAskController' => 'applications/ponder/controller/PonderQuestionAskController.php',
|
||||||
|
'PonderQuestionDetailView' => 'applications/ponder/view/PonderQuestionDetailView.php',
|
||||||
|
'PonderQuestionFeedView' => 'applications/ponder/view/PonderQuestionFeedView.php',
|
||||||
|
'PonderQuestionPreviewController' => 'applications/ponder/controller/PonderQuestionPreviewController.php',
|
||||||
|
'PonderQuestionQuery' => 'applications/ponder/query/PonderQuestionQuery.php',
|
||||||
|
'PonderQuestionSummaryView' => 'applications/ponder/view/PonderQuestionSummaryView.php',
|
||||||
|
'PonderQuestionViewController' => 'applications/ponder/controller/PonderQuestionViewController.php',
|
||||||
|
'PonderRuleQuestion' => 'infrastructure/markup/rule/PonderRuleQuestion.php',
|
||||||
|
'PonderUserProfileView' => 'applications/ponder/view/PonderUserProfileView.php',
|
||||||
|
'PonderVotableInterface' => 'applications/ponder/storage/PonderVotableInterface.php',
|
||||||
|
'PonderVotableView' => 'applications/ponder/view/PonderVotableView.php',
|
||||||
|
'PonderVoteEditor' => 'applications/ponder/editor/PonderVoteEditor.php',
|
||||||
|
'PonderVoteSaveController' => 'applications/ponder/controller/PonderVoteSaveController.php',
|
||||||
'QueryFormattingTestCase' => 'infrastructure/storage/__tests__/QueryFormattingTestCase.php',
|
'QueryFormattingTestCase' => 'infrastructure/storage/__tests__/QueryFormattingTestCase.php',
|
||||||
),
|
),
|
||||||
'function' =>
|
'function' =>
|
||||||
|
@ -1641,6 +1671,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorApplicationManiphest' => 'PhabricatorApplication',
|
'PhabricatorApplicationManiphest' => 'PhabricatorApplication',
|
||||||
'PhabricatorApplicationPeople' => 'PhabricatorApplication',
|
'PhabricatorApplicationPeople' => 'PhabricatorApplication',
|
||||||
'PhabricatorApplicationPhriction' => 'PhabricatorApplication',
|
'PhabricatorApplicationPhriction' => 'PhabricatorApplication',
|
||||||
|
'PhabricatorApplicationPonder' => 'PhabricatorApplication',
|
||||||
'PhabricatorApplicationProject' => 'PhabricatorApplication',
|
'PhabricatorApplicationProject' => 'PhabricatorApplication',
|
||||||
'PhabricatorApplicationSettings' => 'PhabricatorApplication',
|
'PhabricatorApplicationSettings' => 'PhabricatorApplication',
|
||||||
'PhabricatorApplicationStatusView' => 'AphrontView',
|
'PhabricatorApplicationStatusView' => 'AphrontView',
|
||||||
|
@ -2029,6 +2060,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorSearchIndexController' => 'PhabricatorSearchBaseController',
|
'PhabricatorSearchIndexController' => 'PhabricatorSearchBaseController',
|
||||||
'PhabricatorSearchManiphestIndexer' => 'PhabricatorSearchDocumentIndexer',
|
'PhabricatorSearchManiphestIndexer' => 'PhabricatorSearchDocumentIndexer',
|
||||||
'PhabricatorSearchPhrictionIndexer' => 'PhabricatorSearchDocumentIndexer',
|
'PhabricatorSearchPhrictionIndexer' => 'PhabricatorSearchDocumentIndexer',
|
||||||
|
'PhabricatorSearchPonderIndexer' => 'PhabricatorSearchDocumentIndexer',
|
||||||
'PhabricatorSearchQuery' => 'PhabricatorSearchDAO',
|
'PhabricatorSearchQuery' => 'PhabricatorSearchDAO',
|
||||||
'PhabricatorSearchResultView' => 'AphrontView',
|
'PhabricatorSearchResultView' => 'AphrontView',
|
||||||
'PhabricatorSearchSelectController' => 'PhabricatorSearchBaseController',
|
'PhabricatorSearchSelectController' => 'PhabricatorSearchBaseController',
|
||||||
|
@ -2169,6 +2201,40 @@ phutil_register_library_map(array(
|
||||||
'PhrictionEditController' => 'PhrictionController',
|
'PhrictionEditController' => 'PhrictionController',
|
||||||
'PhrictionHistoryController' => 'PhrictionController',
|
'PhrictionHistoryController' => 'PhrictionController',
|
||||||
'PhrictionListController' => 'PhrictionController',
|
'PhrictionListController' => 'PhrictionController',
|
||||||
|
'PonderAddAnswerView' => 'AphrontView',
|
||||||
|
'PonderAnswer' =>
|
||||||
|
array(
|
||||||
|
0 => 'PonderDAO',
|
||||||
|
1 => 'PhabricatorMarkupInterface',
|
||||||
|
2 => 'PonderVotableInterface',
|
||||||
|
),
|
||||||
|
'PonderAnswerListView' => 'AphrontView',
|
||||||
|
'PonderAnswerPreviewController' => 'PonderController',
|
||||||
|
'PonderAnswerQuery' => 'PhabricatorOffsetPagedQuery',
|
||||||
|
'PonderAnswerSaveController' => 'PonderController',
|
||||||
|
'PonderAnswerSummaryView' => 'AphrontView',
|
||||||
|
'PonderAnswerViewController' => 'PonderController',
|
||||||
|
'PonderCommentBodyView' => 'AphrontView',
|
||||||
|
'PonderController' => 'PhabricatorController',
|
||||||
|
'PonderDAO' => 'PhabricatorLiskDAO',
|
||||||
|
'PonderFeedController' => 'PonderController',
|
||||||
|
'PonderQuestion' =>
|
||||||
|
array(
|
||||||
|
0 => 'PonderDAO',
|
||||||
|
1 => 'PhabricatorMarkupInterface',
|
||||||
|
2 => 'PonderVotableInterface',
|
||||||
|
),
|
||||||
|
'PonderQuestionAskController' => 'PonderController',
|
||||||
|
'PonderQuestionDetailView' => 'AphrontView',
|
||||||
|
'PonderQuestionFeedView' => 'AphrontView',
|
||||||
|
'PonderQuestionPreviewController' => 'PonderController',
|
||||||
|
'PonderQuestionQuery' => 'PhabricatorOffsetPagedQuery',
|
||||||
|
'PonderQuestionSummaryView' => 'AphrontView',
|
||||||
|
'PonderQuestionViewController' => 'PonderController',
|
||||||
|
'PonderRuleQuestion' => 'PhabricatorRemarkupRuleObjectName',
|
||||||
|
'PonderUserProfileView' => 'AphrontView',
|
||||||
|
'PonderVotableView' => 'AphrontView',
|
||||||
|
'PonderVoteSaveController' => 'PonderController',
|
||||||
'QueryFormattingTestCase' => 'PhabricatorTestCase',
|
'QueryFormattingTestCase' => 'PhabricatorTestCase',
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
|
|
|
@ -320,7 +320,6 @@ class AphrontDefaultApplicationConfiguration
|
||||||
|
|
||||||
'/emailverify/(?P<code>[^/]+)/' =>
|
'/emailverify/(?P<code>[^/]+)/' =>
|
||||||
'PhabricatorEmailVerificationController',
|
'PhabricatorEmailVerificationController',
|
||||||
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,4 +42,6 @@ final class PhabricatorPHIDConstants {
|
||||||
const PHID_TYPE_POST = 'POST';
|
const PHID_TYPE_POST = 'POST';
|
||||||
const PHID_TYPE_TOBJ = 'TOBJ';
|
const PHID_TYPE_TOBJ = 'TOBJ';
|
||||||
const PHID_TYPE_BLOG = 'BLOG';
|
const PHID_TYPE_BLOG = 'BLOG';
|
||||||
|
const PHID_TYPE_QUES = 'QUES';
|
||||||
|
const PHID_TYPE_ANSW = 'ANSW';
|
||||||
}
|
}
|
||||||
|
|
|
@ -439,6 +439,27 @@ final class PhabricatorObjectHandleData {
|
||||||
$handles[$phid] = $handle;
|
$handles[$phid] = $handle;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case PhabricatorPHIDConstants::PHID_TYPE_QUES:
|
||||||
|
$questions = id(new PonderQuestionQuery())
|
||||||
|
->withPHIDs($phids)
|
||||||
|
->execute();
|
||||||
|
$questions = mpull($questions, 'getPHID');
|
||||||
|
|
||||||
|
foreach ($phids as $phid) {
|
||||||
|
$handle = new PhabricatorObjectHandle();
|
||||||
|
$handle->setPHID($phid);
|
||||||
|
$handle->setType($type);
|
||||||
|
if (empty($questions[$phid])) {
|
||||||
|
$handle->setName('Unknown Ponder Question');
|
||||||
|
} else {
|
||||||
|
$question = $questions[$phid];
|
||||||
|
$handle->setName(phutil_utf8_shorten($question->getTitle(), 60));
|
||||||
|
$handle->setURI(new PhutilURI('Q' . $question->getID()));
|
||||||
|
$handle->setComplete(true);
|
||||||
|
}
|
||||||
|
$handles[$phid] = $handle;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
$loader = null;
|
$loader = null;
|
||||||
if (isset($external_loaders[$type])) {
|
if (isset($external_loaders[$type])) {
|
||||||
|
|
26
src/applications/ponder/PonderConstants.php
Normal file
26
src/applications/ponder/PonderConstants.php
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2012 Facebook, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
final class PonderConstants {
|
||||||
|
const UP_VOTE = 1;
|
||||||
|
const NONE_VOTE = 0;
|
||||||
|
const DOWN_VOTE = -1;
|
||||||
|
|
||||||
|
const ANSWERED_LITERAL = "answered";
|
||||||
|
const ASKED_LITERAL = "asked";
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2012 Facebook, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
final class PhabricatorApplicationPonder extends PhabricatorApplication {
|
||||||
|
|
||||||
|
public function getBaseURI() {
|
||||||
|
return '/ponder/';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getShortDescription() {
|
||||||
|
return 'Find Answers';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getIconURI() {
|
||||||
|
return celerity_get_resource_uri('/rsrc/image/app/app_ponder.png');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFactObjectsForAnalysis() {
|
||||||
|
return array(
|
||||||
|
new PonderQuestion(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function loadStatus(PhabricatorUser $user) {
|
||||||
|
// replace with "x new unanswered questions" or some such
|
||||||
|
$status = array();
|
||||||
|
|
||||||
|
return $status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getroutes() {
|
||||||
|
return array(
|
||||||
|
'/Q(?P<id>\d+)' => 'PonderQuestionViewController',
|
||||||
|
'/ponder/' => array(
|
||||||
|
'(?P<page>feed/)?' => 'PonderFeedController',
|
||||||
|
'(?P<page>profile)/' => 'PonderFeedController',
|
||||||
|
'answer/add/' => 'PonderAnswerSaveController',
|
||||||
|
'answer/preview/' => 'PonderAnswerPreviewController',
|
||||||
|
'question/ask/' => 'PonderQuestionAskController',
|
||||||
|
'question/preview/' => 'PonderQuestionPreviewController',
|
||||||
|
'(?P<kind>question)/vote/' => 'PonderVoteSaveController',
|
||||||
|
'(?P<kind>answer)/vote/' => 'PonderVoteSaveController'
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2012 Facebook, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
final class PonderAnswerPreviewController
|
||||||
|
extends PonderController {
|
||||||
|
|
||||||
|
public function processRequest() {
|
||||||
|
|
||||||
|
$request = $this->getRequest();
|
||||||
|
$user = $request->getUser();
|
||||||
|
$question_id = $request->getInt('question_id');
|
||||||
|
|
||||||
|
$question = PonderQuestionQuery::loadSingle($user, $question_id);
|
||||||
|
if (!$question) {
|
||||||
|
return new Aphront404Response();
|
||||||
|
}
|
||||||
|
|
||||||
|
$author_phid = $user->getPHID();
|
||||||
|
$object_phids = array($author_phid);
|
||||||
|
$handles = id(new PhabricatorObjectHandleData($object_phids))
|
||||||
|
->loadHandles();
|
||||||
|
|
||||||
|
$answer = new PonderAnswer();
|
||||||
|
$answer->setContent($request->getStr('content'));
|
||||||
|
$answer->setAuthorPHID($author_phid);
|
||||||
|
|
||||||
|
$view = new PonderCommentBodyView();
|
||||||
|
$view
|
||||||
|
->setQuestion($question)
|
||||||
|
->setTarget($answer)
|
||||||
|
->setPreview(true)
|
||||||
|
->setUser($user)
|
||||||
|
->setHandles($handles)
|
||||||
|
->setAction(PonderConstants::ANSWERED_LITERAL);
|
||||||
|
|
||||||
|
return id(new AphrontAjaxResponse())
|
||||||
|
->setContent($view->render());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2012 Facebook, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
final class PonderAnswerSaveController extends PonderController {
|
||||||
|
|
||||||
|
public function processRequest() {
|
||||||
|
$request = $this->getRequest();
|
||||||
|
if (!$request->isFormPost()) {
|
||||||
|
return new Aphront400Response();
|
||||||
|
}
|
||||||
|
|
||||||
|
$user = $request->getUser();
|
||||||
|
$question_id = $request->getInt('question_id');
|
||||||
|
$question = PonderQuestionQuery::loadSingle($user, $question_id);
|
||||||
|
|
||||||
|
if (!$question) {
|
||||||
|
return new Aphront404Response();
|
||||||
|
}
|
||||||
|
|
||||||
|
$answer = $request->getStr('answer');
|
||||||
|
|
||||||
|
$content_source = PhabricatorContentSource::newForSource(
|
||||||
|
PhabricatorContentSource::SOURCE_WEB,
|
||||||
|
array(
|
||||||
|
'ip' => $request->getRemoteAddr(),
|
||||||
|
));
|
||||||
|
|
||||||
|
$res = new PonderAnswer();
|
||||||
|
$res
|
||||||
|
->setContent($answer)
|
||||||
|
->setAuthorPHID($user->getPHID())
|
||||||
|
->setVoteCount(0)
|
||||||
|
->setQuestionID($question_id)
|
||||||
|
->setContentSource($content_source);
|
||||||
|
|
||||||
|
id(new PonderAnswerEditor())
|
||||||
|
->setQuestion($question)
|
||||||
|
->setAnswer($res)
|
||||||
|
->saveAnswer();
|
||||||
|
|
||||||
|
PhabricatorSearchPonderIndexer::indexQuestion($question);
|
||||||
|
|
||||||
|
return id(new AphrontRedirectResponse())
|
||||||
|
->setURI(id(new PhutilURI('/Q'. $question->getID()))
|
||||||
|
->setFragment('A'.$res->getID()));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2012 Facebook, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
final class PonderAnswerViewController extends PonderController {
|
||||||
|
|
||||||
|
private $answerID;
|
||||||
|
|
||||||
|
public function willProcessRequest(array $data) {
|
||||||
|
$this->answerID = $data['id'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function processRequest() {
|
||||||
|
$request = $this->getRequest();
|
||||||
|
$answer = id(new PonderAnswer())->load($this->answerID);
|
||||||
|
|
||||||
|
if (!$answer) {
|
||||||
|
return new Aphront404Response();
|
||||||
|
}
|
||||||
|
|
||||||
|
$question_id = $answer->getQuestionID();
|
||||||
|
|
||||||
|
return id(new AphrontRedirectResponse())
|
||||||
|
->setURI('/Q'.$question_id . '#A' . $answer->getID());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
35
src/applications/ponder/controller/PonderController.php
Normal file
35
src/applications/ponder/controller/PonderController.php
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2012 Facebook, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
abstract class PonderController extends PhabricatorController {
|
||||||
|
|
||||||
|
public function buildStandardPageResponse($view, array $data) {
|
||||||
|
|
||||||
|
$page = $this->buildStandardPageView();
|
||||||
|
$page->setApplicationName('Ponder!');
|
||||||
|
$page->setBaseURI('/ponder/');
|
||||||
|
$page->setTitle(idx($data, 'title'));
|
||||||
|
$page->setGlyph("\xE2\x97\xB3");
|
||||||
|
$page->appendChild($view);
|
||||||
|
$page->setSearchDefaultScope(PhabricatorSearchScope::SCOPE_QUESTIONS);
|
||||||
|
|
||||||
|
$response = new AphrontWebpageResponse();
|
||||||
|
return $response->setContent($page->render());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
143
src/applications/ponder/controller/PonderFeedController.php
Normal file
143
src/applications/ponder/controller/PonderFeedController.php
Normal file
|
@ -0,0 +1,143 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2012 Facebook, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
final class PonderFeedController extends PonderController {
|
||||||
|
private $page;
|
||||||
|
private $feedOffset;
|
||||||
|
private $questionOffset;
|
||||||
|
private $answerOffset;
|
||||||
|
|
||||||
|
const PAGE_FEED = "feed";
|
||||||
|
const PAGE_PROFILE = "profile";
|
||||||
|
|
||||||
|
const FEED_PAGE_SIZE = 20;
|
||||||
|
const PROFILE_QUESTION_PAGE_SIZE = 10;
|
||||||
|
const PROFILE_ANSWER_PAGE_SIZE = 10;
|
||||||
|
|
||||||
|
static $pages = array(
|
||||||
|
self::PAGE_FEED => "Popular Questions",
|
||||||
|
self::PAGE_PROFILE => "User Profile"
|
||||||
|
);
|
||||||
|
|
||||||
|
public function willProcessRequest(array $data) {
|
||||||
|
if (isset($data['page'])) {
|
||||||
|
$this->page = $data['page'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset(self::$pages[$this->page])) {
|
||||||
|
$this->page = self::PAGE_FEED;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->feedOffset = 0;
|
||||||
|
if (isset($data['feedoffset'])) {
|
||||||
|
$this->feedOffset = $data['feedoffset'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function processRequest() {
|
||||||
|
$request = $this->getRequest();
|
||||||
|
$user = $request->getUser();
|
||||||
|
$this->feedOffset = $request->getInt('off');
|
||||||
|
$this->questionOffset = $request->getInt('qoff');
|
||||||
|
$this->answerOffset = $request->getInt('aoff');
|
||||||
|
|
||||||
|
$side_nav = new AphrontSideNavView();
|
||||||
|
foreach (self::$pages as $pagename => $pagetitle) {
|
||||||
|
$class = "";
|
||||||
|
if ($pagename == $this->page) {
|
||||||
|
$class = 'aphront-side-nav-selected';
|
||||||
|
}
|
||||||
|
|
||||||
|
$linky = phutil_render_tag(
|
||||||
|
'a',
|
||||||
|
array(
|
||||||
|
'href' => '/ponder/'.$pagename .'/',
|
||||||
|
'class' => $class
|
||||||
|
),
|
||||||
|
phutil_escape_html($pagetitle)
|
||||||
|
);
|
||||||
|
|
||||||
|
$side_nav->addNavItem($linky);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($this->page) {
|
||||||
|
case self::PAGE_FEED:
|
||||||
|
$data = PonderQuestionQuery::loadHottest(
|
||||||
|
$user,
|
||||||
|
$this->feedOffset,
|
||||||
|
self::FEED_PAGE_SIZE + 1);
|
||||||
|
|
||||||
|
$phids = array();
|
||||||
|
foreach ($data as $question) {
|
||||||
|
$phids[] = $question->getAuthorPHID();
|
||||||
|
}
|
||||||
|
$handles = id(new PhabricatorObjectHandleData($phids))
|
||||||
|
->loadHandles();
|
||||||
|
|
||||||
|
$side_nav->appendChild(
|
||||||
|
id(new PonderQuestionFeedView())
|
||||||
|
->setUser($user)
|
||||||
|
->setData($data)
|
||||||
|
->setHandles($handles)
|
||||||
|
->setOffset($this->feedOffset)
|
||||||
|
->setPageSize(self::FEED_PAGE_SIZE)
|
||||||
|
->setURI(new PhutilURI("/ponder/feed/"), "off")
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case self::PAGE_PROFILE:
|
||||||
|
$questions = PonderQuestionQuery::loadByAuthor(
|
||||||
|
$user,
|
||||||
|
$user->getPHID(),
|
||||||
|
$this->questionOffset,
|
||||||
|
self::PROFILE_QUESTION_PAGE_SIZE + 1
|
||||||
|
);
|
||||||
|
|
||||||
|
$answers = PonderAnswerQuery::loadByAuthorWithQuestions(
|
||||||
|
$user,
|
||||||
|
$user->getPHID(),
|
||||||
|
$this->answerOffset,
|
||||||
|
self::PROFILE_ANSWER_PAGE_SIZE + 1
|
||||||
|
);
|
||||||
|
|
||||||
|
$phids = array($user->getPHID());
|
||||||
|
$handles = id(new PhabricatorObjectHandleData($phids))
|
||||||
|
->loadHandles();
|
||||||
|
|
||||||
|
$side_nav->appendChild(
|
||||||
|
id(new PonderUserProfileView())
|
||||||
|
->setUser($user)
|
||||||
|
->setQuestions($questions)
|
||||||
|
->setAnswers($answers)
|
||||||
|
->setHandles($handles)
|
||||||
|
->setQuestionOffset($this->questionOffset)
|
||||||
|
->setAnswerOffset($this->answerOffset)
|
||||||
|
->setPageSize(self::PROFILE_QUESTION_PAGE_SIZE)
|
||||||
|
->setURI(new PhutilURI("/ponder/profile/"), "qoff", "aoff")
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return $this->buildStandardPageResponse(
|
||||||
|
$side_nav,
|
||||||
|
array(
|
||||||
|
'title' => self::$pages[$this->page]
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,152 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2012 Facebook, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
final class PonderQuestionAskController extends PonderController {
|
||||||
|
|
||||||
|
public function processRequest() {
|
||||||
|
$request = $this->getRequest();
|
||||||
|
$user = $request->getUser();
|
||||||
|
|
||||||
|
if ($request->isFormPost()) {
|
||||||
|
return $this->handlePost();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->showForm();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function handlePost() {
|
||||||
|
$request = $this->getRequest();
|
||||||
|
$user = $request->getUser();
|
||||||
|
|
||||||
|
$errors = array();
|
||||||
|
$title = $request->getStr('title');
|
||||||
|
$content = $request->getStr('content');
|
||||||
|
|
||||||
|
// form validation
|
||||||
|
if (phutil_utf8_strlen($title) < 1 || phutil_utf8_strlen($title) > 255) {
|
||||||
|
$errors[] = "Please enter a title (1-255 characters)";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($errors) {
|
||||||
|
return $this->showForm($errors, $title, $content);
|
||||||
|
}
|
||||||
|
|
||||||
|
// no validation errors -> save it
|
||||||
|
|
||||||
|
$content_source = PhabricatorContentSource::newForSource(
|
||||||
|
PhabricatorContentSource::SOURCE_WEB,
|
||||||
|
array(
|
||||||
|
'ip' => $request->getRemoteAddr(),
|
||||||
|
));
|
||||||
|
|
||||||
|
$question = id(new PonderQuestion())
|
||||||
|
->setTitle($title)
|
||||||
|
->setContent($content)
|
||||||
|
->setAuthorPHID($user->getPHID())
|
||||||
|
->setContentSource($content_source)
|
||||||
|
->setVoteCount(0)
|
||||||
|
->setAnswerCount(0)
|
||||||
|
->setHeat(0.0)
|
||||||
|
->save();
|
||||||
|
|
||||||
|
PhabricatorSearchPonderIndexer::indexQuestion($question);
|
||||||
|
|
||||||
|
return id(new AphrontRedirectResponse())
|
||||||
|
->setURI('/Q'.$question->getID());
|
||||||
|
}
|
||||||
|
|
||||||
|
private function showForm(
|
||||||
|
$errors = null,
|
||||||
|
$title = "",
|
||||||
|
$content = "",
|
||||||
|
$id = null) {
|
||||||
|
|
||||||
|
require_celerity_resource('ponder-core-view-css');
|
||||||
|
require_celerity_resource('phabricator-remarkup-css');
|
||||||
|
require_celerity_resource('ponder-post-css');
|
||||||
|
|
||||||
|
$request = $this->getRequest();
|
||||||
|
$user = $request->getUser();
|
||||||
|
$error_view = null;
|
||||||
|
|
||||||
|
if ($errors) {
|
||||||
|
$error_view = id(new AphrontErrorView())
|
||||||
|
->setTitle('Form Errors')
|
||||||
|
->setErrors($errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
$form = new AphrontFormView();
|
||||||
|
$form->setUser($user);
|
||||||
|
$form->setAction('/ponder/question/ask/');
|
||||||
|
$form
|
||||||
|
->appendChild(
|
||||||
|
id(new AphrontFormTextControl())
|
||||||
|
->setLabel('Title')
|
||||||
|
->setName('title')
|
||||||
|
->setValue($title))
|
||||||
|
->appendChild(
|
||||||
|
id(new AphrontFormTextAreaControl())
|
||||||
|
->setName('content')
|
||||||
|
->setID('content')
|
||||||
|
->setValue($content)
|
||||||
|
->setLabel("Question")
|
||||||
|
->setCaption(phutil_render_tag(
|
||||||
|
'a',
|
||||||
|
array(
|
||||||
|
'href' => PhabricatorEnv::getDoclink(
|
||||||
|
'article/Remarkup_Reference.html'),
|
||||||
|
'tabindex' => '-1',
|
||||||
|
'target' => '_blank',
|
||||||
|
),
|
||||||
|
"Formatting Reference")))
|
||||||
|
->appendChild(
|
||||||
|
id(new AphrontFormSubmitControl())
|
||||||
|
->setValue('Ask Away!'));
|
||||||
|
|
||||||
|
$panel = id(new AphrontPanelView())
|
||||||
|
->addClass("ponder-panel")
|
||||||
|
->setHeader("Your Question:")
|
||||||
|
->appendChild($error_view)
|
||||||
|
->appendChild($form);
|
||||||
|
|
||||||
|
$panel->appendChild(
|
||||||
|
'<div class="aphront-panel-flush">'.
|
||||||
|
'<div id="question-preview">'.
|
||||||
|
'<span class="aphront-panel-preview-loading-text">'.
|
||||||
|
'Loading question preview...'.
|
||||||
|
'</span>'.
|
||||||
|
'</div>'.
|
||||||
|
'</div>'
|
||||||
|
);
|
||||||
|
|
||||||
|
Javelin::initBehavior(
|
||||||
|
'ponder-feedback-preview',
|
||||||
|
array(
|
||||||
|
'uri' => '/ponder/question/preview/',
|
||||||
|
'content' => 'content',
|
||||||
|
'preview' => 'question-preview',
|
||||||
|
'question_id' => null
|
||||||
|
));
|
||||||
|
|
||||||
|
return $this->buildStandardPageResponse(
|
||||||
|
array($panel),
|
||||||
|
array('title' => 'Ask a Question')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2012 Facebook, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
final class PonderQuestionPreviewController
|
||||||
|
extends PonderController {
|
||||||
|
|
||||||
|
const VERB_ASKED = "asked";
|
||||||
|
|
||||||
|
public function processRequest() {
|
||||||
|
|
||||||
|
$request = $this->getRequest();
|
||||||
|
|
||||||
|
$user = $request->getUser();
|
||||||
|
$author_phid = $user->getPHID();
|
||||||
|
|
||||||
|
$object_phids = array($author_phid);
|
||||||
|
$handles = id(new PhabricatorObjectHandleData($object_phids))
|
||||||
|
->loadHandles();
|
||||||
|
|
||||||
|
$question = new PonderQuestion();
|
||||||
|
$question->setContent($request->getStr('content'));
|
||||||
|
$question->setAuthorPHID($author_phid);
|
||||||
|
|
||||||
|
$view = new PonderCommentBodyView();
|
||||||
|
$view
|
||||||
|
->setQuestion($question)
|
||||||
|
->setTarget($question)
|
||||||
|
->setPreview(true)
|
||||||
|
->setUser($user)
|
||||||
|
->setHandles($handles)
|
||||||
|
->setAction(self::VERB_ASKED);
|
||||||
|
|
||||||
|
return id(new AphrontAjaxResponse())
|
||||||
|
->setContent($view->render());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,76 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2012 Facebook, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
final class PonderQuestionViewController extends PonderController {
|
||||||
|
|
||||||
|
private $questionID;
|
||||||
|
|
||||||
|
public function willProcessRequest(array $data) {
|
||||||
|
$this->questionID = $data['id'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function processRequest() {
|
||||||
|
|
||||||
|
$request = $this->getRequest();
|
||||||
|
$user = $request->getUser();
|
||||||
|
|
||||||
|
$question = PonderQuestionQuery::loadSingle($user, $this->questionID);
|
||||||
|
if (!$question) {
|
||||||
|
return new Aphront404Response();
|
||||||
|
}
|
||||||
|
$question->attachRelated($user->getPHID());
|
||||||
|
$answers = $question->getAnswers();
|
||||||
|
|
||||||
|
$object_phids = array($user->getPHID(), $question->getAuthorPHID());
|
||||||
|
foreach ($answers as $answer) {
|
||||||
|
$object_phids[] = $answer->getAuthorPHID();
|
||||||
|
}
|
||||||
|
|
||||||
|
$handles = id(new PhabricatorObjectHandleData($object_phids))
|
||||||
|
->loadHandles();
|
||||||
|
|
||||||
|
$detail_panel = new PonderQuestionDetailView();
|
||||||
|
$detail_panel
|
||||||
|
->setQuestion($question)
|
||||||
|
->setUser($user)
|
||||||
|
->setHandles($handles);
|
||||||
|
|
||||||
|
$responses_panel = new PonderAnswerListView();
|
||||||
|
$responses_panel
|
||||||
|
->setQuestion($question)
|
||||||
|
->setHandles($handles)
|
||||||
|
->setUser($user)
|
||||||
|
->setAnswers($answers);
|
||||||
|
|
||||||
|
$answer_add_panel = new PonderAddAnswerView();
|
||||||
|
$answer_add_panel
|
||||||
|
->setQuestion($question)
|
||||||
|
->setUser($user)
|
||||||
|
->setActionURI("/ponder/answer/add/");
|
||||||
|
|
||||||
|
return $this->buildStandardPageResponse(
|
||||||
|
array(
|
||||||
|
$detail_panel,
|
||||||
|
$responses_panel,
|
||||||
|
$answer_add_panel
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'title' => 'Q'.$question->getID().' '.$question->getTitle()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2012 Facebook, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
final class PonderVoteSaveController extends PonderController {
|
||||||
|
|
||||||
|
private $kind;
|
||||||
|
|
||||||
|
public function willProcessRequest(array $data) {
|
||||||
|
$this->kind = $data['kind'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function processRequest() {
|
||||||
|
$request = $this->getRequest();
|
||||||
|
$user = $request->getUser();
|
||||||
|
$newvote = $request->getInt("vote");
|
||||||
|
$phid = $request->getStr("phid");
|
||||||
|
|
||||||
|
if (1 < $newvote || $newvote < -1) {
|
||||||
|
return new Aphront400Response();
|
||||||
|
}
|
||||||
|
|
||||||
|
$target = null;
|
||||||
|
|
||||||
|
if ($this->kind == "question") {
|
||||||
|
$target = PonderQuestionQuery::loadSingleByPHID($user, $phid);
|
||||||
|
}
|
||||||
|
else if ($this->kind == "answer") {
|
||||||
|
$target = PonderAnswerQuery::loadSingleByPHID($user, $phid);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$target) {
|
||||||
|
return new Aphront404Response();
|
||||||
|
}
|
||||||
|
|
||||||
|
$editor = id(new PonderVoteEditor())
|
||||||
|
->setVotable($target)
|
||||||
|
->setUser($user)
|
||||||
|
->setVote($newvote)
|
||||||
|
->saveVote();
|
||||||
|
|
||||||
|
return id(new AphrontAjaxResponse())->setContent(".");
|
||||||
|
}
|
||||||
|
}
|
64
src/applications/ponder/editor/PonderAnswerEditor.php
Normal file
64
src/applications/ponder/editor/PonderAnswerEditor.php
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2012 Facebook, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
final class PonderAnswerEditor {
|
||||||
|
|
||||||
|
private $question;
|
||||||
|
private $answer;
|
||||||
|
|
||||||
|
public function setQuestion($question) {
|
||||||
|
$this->question = $question;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setAnswer($answer) {
|
||||||
|
$this->answer = $answer;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function saveAnswer() {
|
||||||
|
if (!$this->question) {
|
||||||
|
throw new Exception("Must set question before saving vote");
|
||||||
|
}
|
||||||
|
if (!$this->answer) {
|
||||||
|
throw new Exception("Must set answer before saving vote");
|
||||||
|
}
|
||||||
|
|
||||||
|
$question = $this->question;
|
||||||
|
$answer = $this->answer;
|
||||||
|
$conn = $answer->establishConnection('w');
|
||||||
|
$trans = $conn->openTransaction();
|
||||||
|
$trans->beginReadLocking();
|
||||||
|
|
||||||
|
$question->reload();
|
||||||
|
|
||||||
|
queryfx($conn,
|
||||||
|
'UPDATE %T as t
|
||||||
|
SET t.`answerCount` = t.`answerCount` + 1
|
||||||
|
WHERE t.`PHID` = %s',
|
||||||
|
$question->getTableName(),
|
||||||
|
$question->getPHID());
|
||||||
|
|
||||||
|
$answer->setQuestionID($question->getID());
|
||||||
|
$answer->save();
|
||||||
|
|
||||||
|
$trans->endReadLocking();
|
||||||
|
$trans->saveTransaction();
|
||||||
|
}
|
||||||
|
}
|
104
src/applications/ponder/editor/PonderVoteEditor.php
Normal file
104
src/applications/ponder/editor/PonderVoteEditor.php
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2012 Facebook, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
final class PonderVoteEditor {
|
||||||
|
|
||||||
|
private $answer;
|
||||||
|
private $votable;
|
||||||
|
private $anwer;
|
||||||
|
private $user;
|
||||||
|
private $vote;
|
||||||
|
|
||||||
|
public function setAnswer($answer) {
|
||||||
|
$this->answer = $answer;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setVotable($votable) {
|
||||||
|
$this->votable = $votable;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setUser($user) {
|
||||||
|
$this->user = $user;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setVote($vote) {
|
||||||
|
$this->vote = $vote;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function saveVote() {
|
||||||
|
if (!$this->votable) {
|
||||||
|
throw new Exception("Must set votable before saving vote");
|
||||||
|
}
|
||||||
|
if (!$this->user) {
|
||||||
|
throw new Exception("Must set user before saving vote");
|
||||||
|
}
|
||||||
|
|
||||||
|
$user = $this->user;
|
||||||
|
$votable = $this->votable;
|
||||||
|
$newvote = $this->vote;
|
||||||
|
|
||||||
|
// prepare vote add, or update if this user is amending an
|
||||||
|
// earlier vote
|
||||||
|
$editor = id(new PhabricatorEdgeEditor())
|
||||||
|
->setUser($user)
|
||||||
|
->addEdge(
|
||||||
|
$user->getPHID(),
|
||||||
|
$votable->getUserVoteEdgeType(),
|
||||||
|
$votable->getVotablePHID(),
|
||||||
|
array('data' => $newvote))
|
||||||
|
->removeEdge(
|
||||||
|
$user->getPHID(),
|
||||||
|
$votable->getUserVoteEdgeType(),
|
||||||
|
$votable->getVotablePHID());
|
||||||
|
|
||||||
|
$conn = $votable->establishConnection('w');
|
||||||
|
$trans = $conn->openTransaction();
|
||||||
|
$trans->beginReadLocking();
|
||||||
|
|
||||||
|
$votable->reload();
|
||||||
|
$curvote = (int)PhabricatorEdgeQuery::loadSingleEdgeData(
|
||||||
|
$user->getPHID(),
|
||||||
|
$votable->getUserVoteEdgeType(),
|
||||||
|
$votable->getVotablePHID());
|
||||||
|
|
||||||
|
if (!$curvote) {
|
||||||
|
$curvote = PonderConstants::NONE_VOTE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// adjust votable's score by this much
|
||||||
|
$delta = $newvote - $curvote;
|
||||||
|
|
||||||
|
queryfx($conn,
|
||||||
|
'UPDATE %T as t
|
||||||
|
SET t.`voteCount` = t.`voteCount` + %d
|
||||||
|
WHERE t.`PHID` = %s',
|
||||||
|
$votable->getTableName(),
|
||||||
|
$delta,
|
||||||
|
$votable->getVotablePHID());
|
||||||
|
|
||||||
|
$editor->save();
|
||||||
|
|
||||||
|
$trans->endReadLocking();
|
||||||
|
$trans->saveTransaction();
|
||||||
|
}
|
||||||
|
}
|
161
src/applications/ponder/query/PonderAnswerQuery.php
Normal file
161
src/applications/ponder/query/PonderAnswerQuery.php
Normal file
|
@ -0,0 +1,161 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2012 Facebook, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
final class PonderAnswerQuery extends PhabricatorOffsetPagedQuery {
|
||||||
|
|
||||||
|
private $id;
|
||||||
|
private $phid;
|
||||||
|
private $authorPHID;
|
||||||
|
private $orderNewest;
|
||||||
|
|
||||||
|
public function withID($qid) {
|
||||||
|
$this->id = $qid;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function withPHID($phid) {
|
||||||
|
$this->phid = $phid;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function withAuthorPHID($phid) {
|
||||||
|
$this->authorPHID = $phid;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function orderByNewest($usethis) {
|
||||||
|
$this->orderNewest = $usethis;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function loadByAuthorWithQuestions(
|
||||||
|
$viewer,
|
||||||
|
$phid,
|
||||||
|
$offset,
|
||||||
|
$count) {
|
||||||
|
|
||||||
|
if (!$viewer) {
|
||||||
|
throw new Exception("Must set viewer when calling loadByAuthor...");
|
||||||
|
}
|
||||||
|
|
||||||
|
$answers = id(new PonderAnswerQuery())
|
||||||
|
->withAuthorPHID($phid)
|
||||||
|
->orderByNewest(true)
|
||||||
|
->setOffset($offset)
|
||||||
|
->setLimit($count)
|
||||||
|
->execute();
|
||||||
|
|
||||||
|
$answerset = new LiskDAOSet();
|
||||||
|
foreach ($answers as $answer) {
|
||||||
|
$answerset->addToSet($answer);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($answers as $answer) {
|
||||||
|
$question = $answer->loadOneRelative(
|
||||||
|
new PonderQuestion(),
|
||||||
|
'id',
|
||||||
|
'getQuestionID');
|
||||||
|
$answer->setQuestion($question);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $answers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function loadByAuthor($viewer, $author_phid, $offset, $count) {
|
||||||
|
if (!$viewer) {
|
||||||
|
throw new Exception("Must set viewer when calling loadByAuthor");
|
||||||
|
}
|
||||||
|
|
||||||
|
return id(new PonderAnswerQuery())
|
||||||
|
->withAuthorPHID($author_phid)
|
||||||
|
->setOffset($offset)
|
||||||
|
->setLimit($count)
|
||||||
|
->orderByNewest(true)
|
||||||
|
->execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function loadSingle($viewer, $id) {
|
||||||
|
if (!$viewer) {
|
||||||
|
throw new Exception("Must set viewer when calling loadSingle");
|
||||||
|
}
|
||||||
|
return idx(id(new PonderAnswerQuery())
|
||||||
|
->withID($id)
|
||||||
|
->execute(), $id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function loadSingleByPHID($viewer, $phid) {
|
||||||
|
if (!$viewer) {
|
||||||
|
throw new Exception("Must set viewer when calling loadSingle");
|
||||||
|
}
|
||||||
|
|
||||||
|
return array_shift(id(new PonderAnswerQuery())
|
||||||
|
->withPHID($phid)
|
||||||
|
->execute());
|
||||||
|
}
|
||||||
|
|
||||||
|
private function buildWhereClause($conn_r) {
|
||||||
|
$where = array();
|
||||||
|
if ($this->id) {
|
||||||
|
$where[] = qsprintf($conn_r, '(id = %d)', $this->id);
|
||||||
|
}
|
||||||
|
if ($this->phid) {
|
||||||
|
$where[] = qsprintf($conn_r, '(phid = %s)', $this->phid);
|
||||||
|
}
|
||||||
|
if ($this->authorPHID) {
|
||||||
|
$where[] = qsprintf($conn_r, '(authorPHID = %s)', $this->authorPHID);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->formatWhereClause($where);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function buildOrderByClause($conn_r) {
|
||||||
|
$order = array();
|
||||||
|
if ($this->orderNewest) {
|
||||||
|
$order[] = qsprintf($conn_r, 'id DESC');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count($order) == 0) {
|
||||||
|
$order[] = qsprintf($conn_r, 'id ASC');
|
||||||
|
}
|
||||||
|
|
||||||
|
return ($order ? 'ORDER BY ' . implode(', ', $order) : '');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function execute() {
|
||||||
|
$answer = new PonderAnswer();
|
||||||
|
$conn_r = $answer->establishConnection('r');
|
||||||
|
|
||||||
|
$select = qsprintf(
|
||||||
|
$conn_r,
|
||||||
|
'SELECT r.* FROM %T r',
|
||||||
|
$answer->getTableName());
|
||||||
|
|
||||||
|
$where = $this->buildWhereClause($conn_r);
|
||||||
|
$order_by = $this->buildOrderByClause($conn_r);
|
||||||
|
$limit = $this->buildLimitClause($conn_r);
|
||||||
|
|
||||||
|
return $answer->loadAllFromArray(
|
||||||
|
queryfx_all(
|
||||||
|
$conn_r,
|
||||||
|
'%Q %Q %Q %Q',
|
||||||
|
$select,
|
||||||
|
$where,
|
||||||
|
$order_by,
|
||||||
|
$limit));
|
||||||
|
}
|
||||||
|
}
|
157
src/applications/ponder/query/PonderQuestionQuery.php
Normal file
157
src/applications/ponder/query/PonderQuestionQuery.php
Normal file
|
@ -0,0 +1,157 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2012 Facebook, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
final class PonderQuestionQuery extends PhabricatorOffsetPagedQuery {
|
||||||
|
|
||||||
|
private $id;
|
||||||
|
private $phids;
|
||||||
|
private $authorPHID;
|
||||||
|
private $orderHottest;
|
||||||
|
private $orderNewest;
|
||||||
|
|
||||||
|
public function withID($qid) {
|
||||||
|
$this->id = $qid;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function withPHID($phid) {
|
||||||
|
$this->phids = array($phid);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function withPHIDs($phids) {
|
||||||
|
$this->phids = $phids;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function withAuthorPHID($phid) {
|
||||||
|
$this->authorPHID = $phid;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function orderByHottest($usethis) {
|
||||||
|
$this->orderHottest = $usethis;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function orderByNewest($usethis) {
|
||||||
|
$this->orderNewest = $usethis;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function loadHottest($viewer, $offset, $count) {
|
||||||
|
if (!$viewer) {
|
||||||
|
throw new Exception("Must set viewer when calling loadHottest");
|
||||||
|
}
|
||||||
|
|
||||||
|
return id(new PonderQuestionQuery())
|
||||||
|
->setOffset($offset)
|
||||||
|
->setLimit($count)
|
||||||
|
->orderByHottest(true)
|
||||||
|
->execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function loadByAuthor($viewer, $author_phid, $offset, $count) {
|
||||||
|
if (!$viewer) {
|
||||||
|
throw new Exception("Must set viewer when calling loadByAuthor");
|
||||||
|
}
|
||||||
|
|
||||||
|
return id(new PonderQuestionQuery())
|
||||||
|
->withAuthorPHID($author_phid)
|
||||||
|
->setOffset($offset)
|
||||||
|
->setLimit($count)
|
||||||
|
->orderByNewest(true)
|
||||||
|
->execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function loadSingle($viewer, $id) {
|
||||||
|
if (!$viewer) {
|
||||||
|
throw new Exception("Must set viewer when calling loadSingle");
|
||||||
|
}
|
||||||
|
|
||||||
|
return idx(id(new PonderQuestionQuery())
|
||||||
|
->withID($id)
|
||||||
|
->execute(), $id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function loadSingleByPHID($viewer, $phid) {
|
||||||
|
if (!$viewer) {
|
||||||
|
throw new Exception("Must set viewer when calling loadSingle");
|
||||||
|
}
|
||||||
|
|
||||||
|
return array_shift(id(new PonderQuestionQuery())
|
||||||
|
->withPHID($phid)
|
||||||
|
->execute());
|
||||||
|
}
|
||||||
|
|
||||||
|
private function buildWhereClause($conn_r) {
|
||||||
|
$where = array();
|
||||||
|
if ($this->id) {
|
||||||
|
$where[] = qsprintf($conn_r, '(id = %d)', $this->id);
|
||||||
|
}
|
||||||
|
if ($this->phids) {
|
||||||
|
$where[] = qsprintf($conn_r, '(phid in (%Ls))', $this->phids);
|
||||||
|
}
|
||||||
|
if ($this->authorPHID) {
|
||||||
|
$where[] = qsprintf($conn_r, '(authorPHID = %s)', $this->authorPHID);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ($where ? 'WHERE ' . implode(' AND ', $where) : '');
|
||||||
|
}
|
||||||
|
|
||||||
|
private function buildOrderByClause($conn_r) {
|
||||||
|
$order = array();
|
||||||
|
if ($this->orderHottest) {
|
||||||
|
$order[] = qsprintf($conn_r, 'heat DESC');
|
||||||
|
}
|
||||||
|
if ($this->orderNewest) {
|
||||||
|
$order[] = qsprintf($conn_r, 'id DESC');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count($order) == 0) {
|
||||||
|
$order[] = qsprintf($conn_r, 'id ASC');
|
||||||
|
}
|
||||||
|
|
||||||
|
return ($order ? 'ORDER BY ' . implode(', ', $order) : '');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function execute() {
|
||||||
|
$question = new PonderQuestion();
|
||||||
|
$conn_r = $question->establishConnection('r');
|
||||||
|
|
||||||
|
$select = qsprintf(
|
||||||
|
$conn_r,
|
||||||
|
'SELECT r.* FROM %T r',
|
||||||
|
$question->getTableName());
|
||||||
|
|
||||||
|
$where = $this->buildWhereClause($conn_r);
|
||||||
|
$order_by = $this->buildOrderByClause($conn_r);
|
||||||
|
$limit = $this->buildLimitClause($conn_r);
|
||||||
|
|
||||||
|
return $question->loadAllFromArray(
|
||||||
|
queryfx_all(
|
||||||
|
$conn_r,
|
||||||
|
'%Q %Q %Q %Q',
|
||||||
|
$select,
|
||||||
|
$where,
|
||||||
|
$order_by,
|
||||||
|
$limit));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2012 Facebook, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
final class PhabricatorSearchPonderIndexer
|
||||||
|
extends PhabricatorSearchDocumentIndexer {
|
||||||
|
|
||||||
|
public static function indexQuestion(PonderQuestion $question) {
|
||||||
|
|
||||||
|
$doc = new PhabricatorSearchAbstractDocument();
|
||||||
|
$doc->setPHID($question->getPHID());
|
||||||
|
$doc->setDocumentType(PhabricatorPHIDConstants::PHID_TYPE_QUES);
|
||||||
|
$doc->setDocumentTitle($question->getTitle());
|
||||||
|
$doc->setDocumentCreated($question->getDateCreated());
|
||||||
|
$doc->setDocumentModified($question->getDateModified());
|
||||||
|
|
||||||
|
$doc->addField(
|
||||||
|
PhabricatorSearchField::FIELD_BODY,
|
||||||
|
$question->getContent());
|
||||||
|
|
||||||
|
$doc->addRelationship(
|
||||||
|
PhabricatorSearchRelationship::RELATIONSHIP_AUTHOR,
|
||||||
|
$question->getAuthorPHID(),
|
||||||
|
PhabricatorPHIDConstants::PHID_TYPE_USER,
|
||||||
|
$question->getDateCreated());
|
||||||
|
|
||||||
|
$answers = $question->getAnswers();
|
||||||
|
$touches = array();
|
||||||
|
foreach ($answers as $comment) {
|
||||||
|
if (strlen($comment->getContent())) {
|
||||||
|
$doc->addField(
|
||||||
|
PhabricatorSearchField::FIELD_COMMENT,
|
||||||
|
$comment->getContent());
|
||||||
|
}
|
||||||
|
|
||||||
|
$author = $comment->getAuthorPHID();
|
||||||
|
$touches[$author] = $comment->getDateCreated();
|
||||||
|
}
|
||||||
|
|
||||||
|
self::reindexAbstractDocument($doc);
|
||||||
|
}
|
||||||
|
}
|
127
src/applications/ponder/storage/PonderAnswer.php
Normal file
127
src/applications/ponder/storage/PonderAnswer.php
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2012 Facebook, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
final class PonderAnswer extends PonderDAO
|
||||||
|
implements PhabricatorMarkupInterface, PonderVotableInterface {
|
||||||
|
|
||||||
|
const MARKUP_FIELD_CONTENT = 'markup:content';
|
||||||
|
|
||||||
|
protected $phid;
|
||||||
|
protected $authorPHID;
|
||||||
|
protected $questionID;
|
||||||
|
|
||||||
|
protected $content;
|
||||||
|
protected $contentSource;
|
||||||
|
|
||||||
|
protected $voteCount;
|
||||||
|
private $vote;
|
||||||
|
private $question = null;
|
||||||
|
|
||||||
|
public function setQuestion($question) {
|
||||||
|
$this->question = $question;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getQuestion() {
|
||||||
|
return $this->question;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setUserVote($vote) {
|
||||||
|
$this->vote = $vote['data'];
|
||||||
|
if (!$this->vote) {
|
||||||
|
$this->vote = PonderConstants::NONE_VOTE;
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getUserVote() {
|
||||||
|
return $this->vote;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getConfiguration() {
|
||||||
|
return array(
|
||||||
|
self::CONFIG_AUX_PHID => true,
|
||||||
|
) + parent::getConfiguration();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setTitle($title) {
|
||||||
|
$this->title = $title;
|
||||||
|
if (!$this->getID()) {
|
||||||
|
$this->originalTitle = $title;
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function generatePHID() {
|
||||||
|
return PhabricatorPHID::generateNewPHID(
|
||||||
|
PhabricatorPHIDConstants::PHID_TYPE_ANSW);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setContentSource(PhabricatorContentSource $content_source) {
|
||||||
|
$this->contentSource = $content_source->serialize();
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getContentSource() {
|
||||||
|
return PhabricatorContentSource::newFromSerialized($this->contentSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAnswers() {
|
||||||
|
return $this->loadRelatives(new PonderAnswer(), "questionID");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMarkupField() {
|
||||||
|
return self::MARKUP_FIELD_CONTENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Markup interface
|
||||||
|
|
||||||
|
public function getMarkupFieldKey($field) {
|
||||||
|
$hash = PhabricatorHash::digest($this->getMarkupText($field));
|
||||||
|
$id = $this->getID();
|
||||||
|
return "ponder:A{$id}:{$field}:{$hash}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMarkupText($field) {
|
||||||
|
return $this->getContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function newMarkupEngine($field) {
|
||||||
|
return PhabricatorMarkupEngine::newPonderMarkupEngine();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function didMarkupText(
|
||||||
|
$field,
|
||||||
|
$output,
|
||||||
|
PhutilMarkupEngine $engine) {
|
||||||
|
return $output;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function shouldUseMarkupCache($field) {
|
||||||
|
return (bool)$this->getID();
|
||||||
|
}
|
||||||
|
|
||||||
|
// votable interface
|
||||||
|
public function getUserVoteEdgeType() {
|
||||||
|
return PhabricatorEdgeConfig::TYPE_VOTING_USER_HAS_ANSWER;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getVotablePHID() {
|
||||||
|
return $this->getPHID();
|
||||||
|
}
|
||||||
|
}
|
25
src/applications/ponder/storage/PonderDAO.php
Normal file
25
src/applications/ponder/storage/PonderDAO.php
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2012 Facebook, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
abstract class PonderDAO extends PhabricatorLiskDAO {
|
||||||
|
|
||||||
|
public function getApplicationName() {
|
||||||
|
return 'ponder';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
141
src/applications/ponder/storage/PonderQuestion.php
Normal file
141
src/applications/ponder/storage/PonderQuestion.php
Normal file
|
@ -0,0 +1,141 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2012 Facebook, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
final class PonderQuestion extends PonderDAO
|
||||||
|
implements PhabricatorMarkupInterface, PonderVotableInterface {
|
||||||
|
|
||||||
|
const MARKUP_FIELD_CONTENT = 'markup:content';
|
||||||
|
|
||||||
|
protected $title;
|
||||||
|
protected $phid;
|
||||||
|
|
||||||
|
protected $authorPHID;
|
||||||
|
protected $content;
|
||||||
|
protected $contentSource;
|
||||||
|
|
||||||
|
protected $voteCount;
|
||||||
|
protected $answerCount;
|
||||||
|
protected $heat;
|
||||||
|
|
||||||
|
private $answers;
|
||||||
|
private $vote;
|
||||||
|
|
||||||
|
public function getConfiguration() {
|
||||||
|
return array(
|
||||||
|
self::CONFIG_AUX_PHID => true,
|
||||||
|
) + parent::getConfiguration();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function generatePHID() {
|
||||||
|
return PhabricatorPHID::generateNewPHID(
|
||||||
|
PhabricatorPHIDConstants::PHID_TYPE_QUES);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setContentSource(PhabricatorContentSource $content_source) {
|
||||||
|
$this->contentSource = $content_source->serialize();
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getContentSource() {
|
||||||
|
return PhabricatorContentSource::newFromSerialized($this->contentSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function attachRelated($user_phid) {
|
||||||
|
$this->answers = $this->loadRelatives(new PonderAnswer(), "questionID");
|
||||||
|
$qa_phids = mpull($this->answers, 'getPHID') + array($this->getPHID());
|
||||||
|
|
||||||
|
$edges = id(new PhabricatorEdgeQuery())
|
||||||
|
->withSourcePHIDs(array($user_phid))
|
||||||
|
->withDestinationPHIDs($qa_phids)
|
||||||
|
->withEdgeTypes(
|
||||||
|
array(
|
||||||
|
PhabricatorEdgeConfig::TYPE_VOTING_USER_HAS_QUESTION,
|
||||||
|
PhabricatorEdgeConfig::TYPE_VOTING_USER_HAS_ANSWER
|
||||||
|
))
|
||||||
|
->needEdgeData(true)
|
||||||
|
->execute();
|
||||||
|
|
||||||
|
$question_edge =
|
||||||
|
$edges[$user_phid][PhabricatorEdgeConfig::TYPE_VOTING_USER_HAS_QUESTION];
|
||||||
|
$answer_edges =
|
||||||
|
$edges[$user_phid][PhabricatorEdgeConfig::TYPE_VOTING_USER_HAS_ANSWER];
|
||||||
|
$edges = null;
|
||||||
|
|
||||||
|
$this->setUserVote(idx($question_edge, $this->getPHID()));
|
||||||
|
foreach ($this->answers as $answer) {
|
||||||
|
$answer->setQuestion($this);
|
||||||
|
$answer->setUserVote(idx($answer_edges, $answer->getPHID()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setUserVote($vote) {
|
||||||
|
$this->vote = $vote['data'];
|
||||||
|
if (!$this->vote) {
|
||||||
|
$this->vote = PonderConstants::NONE_VOTE;
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getUserVote() {
|
||||||
|
return $this->vote;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAnswers() {
|
||||||
|
return $this->answers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMarkupField() {
|
||||||
|
return self::MARKUP_FIELD_CONTENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Markup interface
|
||||||
|
|
||||||
|
public function getMarkupFieldKey($field) {
|
||||||
|
$hash = PhabricatorHash::digest($this->getMarkupText($field));
|
||||||
|
$id = $this->getID();
|
||||||
|
return "ponder:Q{$id}:{$field}:{$hash}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMarkupText($field) {
|
||||||
|
return $this->getContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function newMarkupEngine($field) {
|
||||||
|
return PhabricatorMarkupEngine::newPonderMarkupEngine();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function didMarkupText(
|
||||||
|
$field,
|
||||||
|
$output,
|
||||||
|
PhutilMarkupEngine $engine) {
|
||||||
|
return $output;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function shouldUseMarkupCache($field) {
|
||||||
|
return (bool)$this->getID();
|
||||||
|
}
|
||||||
|
|
||||||
|
// votable interface
|
||||||
|
public function getUserVoteEdgeType() {
|
||||||
|
return PhabricatorEdgeConfig::TYPE_VOTING_USER_HAS_QUESTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getVotablePHID() {
|
||||||
|
return $this->getPHID();
|
||||||
|
}
|
||||||
|
}
|
24
src/applications/ponder/storage/PonderVotableInterface.php
Normal file
24
src/applications/ponder/storage/PonderVotableInterface.php
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2012 Facebook, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
interface PonderVotableInterface {
|
||||||
|
|
||||||
|
public function getUserVoteEdgeType();
|
||||||
|
public function getVotablePHID();
|
||||||
|
|
||||||
|
}
|
97
src/applications/ponder/view/PonderAddAnswerView.php
Normal file
97
src/applications/ponder/view/PonderAddAnswerView.php
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2012 Facebook, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
final class PonderAddAnswerView extends AphrontView {
|
||||||
|
|
||||||
|
private $question;
|
||||||
|
private $user;
|
||||||
|
private $actionURI;
|
||||||
|
private $draft;
|
||||||
|
|
||||||
|
public function setQuestion($question) {
|
||||||
|
$this->question = $question;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setUser(PhabricatorUser $user) {
|
||||||
|
$this->user = $user;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setActionURI($uri) {
|
||||||
|
$this->actionURI = $uri;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function render() {
|
||||||
|
require_celerity_resource('ponder-core-view-css');
|
||||||
|
|
||||||
|
$is_serious = PhabricatorEnv::getEnvConfig('phabricator.serious-business');
|
||||||
|
|
||||||
|
$question = $this->question;
|
||||||
|
|
||||||
|
$panel = id(new AphrontPanelView())
|
||||||
|
->addClass("ponder-panel")
|
||||||
|
->setHeader("Your Answer:");
|
||||||
|
|
||||||
|
$form = new AphrontFormView();
|
||||||
|
$form
|
||||||
|
->setUser($this->user)
|
||||||
|
->setAction($this->actionURI)
|
||||||
|
->addHiddenInput('question_id', $question->getID())
|
||||||
|
->appendChild(
|
||||||
|
id(new AphrontFormTextAreaControl())
|
||||||
|
->setName('answer')
|
||||||
|
->setID('answer-content')
|
||||||
|
->setEnableDragAndDropFileUploads(true)
|
||||||
|
->setCaption(phutil_render_tag(
|
||||||
|
'a',
|
||||||
|
array(
|
||||||
|
'href' => PhabricatorEnv::getDoclink(
|
||||||
|
'article/Remarkup_Reference.html'),
|
||||||
|
'tabindex' => '-1',
|
||||||
|
'target' => '_blank',
|
||||||
|
),
|
||||||
|
'Formatting Reference')))
|
||||||
|
->appendChild(
|
||||||
|
id(new AphrontFormSubmitControl())
|
||||||
|
->setValue($is_serious ? 'Submit' : 'Make it so.'));
|
||||||
|
|
||||||
|
$panel->appendChild($form);
|
||||||
|
$panel->appendChild(
|
||||||
|
'<div class="aphront-panel-flush">'.
|
||||||
|
'<div id="answer-preview">'.
|
||||||
|
'<span class="aphront-panel-preview-loading-text">'.
|
||||||
|
'Loading answer preview...'.
|
||||||
|
'</span>'.
|
||||||
|
'</div>'.
|
||||||
|
'</div>'
|
||||||
|
);
|
||||||
|
|
||||||
|
Javelin::initBehavior(
|
||||||
|
'ponder-feedback-preview',
|
||||||
|
array(
|
||||||
|
'uri' => '/ponder/answer/preview/',
|
||||||
|
'content' => 'answer-content',
|
||||||
|
'preview' => 'answer-preview',
|
||||||
|
'question_id' => $question->getID()
|
||||||
|
));
|
||||||
|
|
||||||
|
return $panel->render();
|
||||||
|
}
|
||||||
|
}
|
89
src/applications/ponder/view/PonderAnswerListView.php
Normal file
89
src/applications/ponder/view/PonderAnswerListView.php
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2012 Facebook, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
final class PonderAnswerListView extends AphrontView {
|
||||||
|
|
||||||
|
private $question;
|
||||||
|
private $handles;
|
||||||
|
private $user;
|
||||||
|
private $answers;
|
||||||
|
|
||||||
|
public function setQuestion($question) {
|
||||||
|
$this->question = $question;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setHandles(array $handles) {
|
||||||
|
assert_instances_of($handles, 'PhabricatorObjectHandle');
|
||||||
|
$this->handles = $handles;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setUser(PhabricatorUser $user) {
|
||||||
|
$this->user = $user;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setAnswers(array $answers) {
|
||||||
|
assert_instances_of($answers, 'PonderAnswer');
|
||||||
|
|
||||||
|
$this->answers = array();
|
||||||
|
|
||||||
|
// group by descreasing score, randomizing
|
||||||
|
// order within groups
|
||||||
|
$by_score = mgroup($answers, 'getVoteCount');
|
||||||
|
$scores = array_keys($by_score);
|
||||||
|
rsort($scores);
|
||||||
|
|
||||||
|
foreach ($scores as $score) {
|
||||||
|
$group = $by_score[$score];
|
||||||
|
shuffle($group);
|
||||||
|
foreach ($group as $cur_answer) {
|
||||||
|
$this->answers[] = $cur_answer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function render() {
|
||||||
|
require_celerity_resource('ponder-post-css');
|
||||||
|
|
||||||
|
$question = $this->question;
|
||||||
|
$user = $this->user;
|
||||||
|
$handles = $this->handles;
|
||||||
|
|
||||||
|
$panel = id(new AphrontPanelView())
|
||||||
|
->addClass("ponder-panel")
|
||||||
|
->setHeader("Responses:");
|
||||||
|
|
||||||
|
foreach ($this->answers as $cur_answer) {
|
||||||
|
$view = new PonderCommentBodyView();
|
||||||
|
$view
|
||||||
|
->setQuestion($question)
|
||||||
|
->setTarget($cur_answer)
|
||||||
|
->setAction(PonderConstants::ANSWERED_LITERAL)
|
||||||
|
->setHandles($handles)
|
||||||
|
->setUser($user);
|
||||||
|
|
||||||
|
$panel->appendChild($view);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $panel->render();
|
||||||
|
}
|
||||||
|
}
|
93
src/applications/ponder/view/PonderAnswerSummaryView.php
Normal file
93
src/applications/ponder/view/PonderAnswerSummaryView.php
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2012 Facebook, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
final class PonderAnswerSummaryView extends AphrontView {
|
||||||
|
private $user;
|
||||||
|
private $answer;
|
||||||
|
private $handles;
|
||||||
|
|
||||||
|
public function setAnswer($answer) {
|
||||||
|
$this->answer = $answer;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setHandles($handles) {
|
||||||
|
$this->handles = $handles;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setUser(PhabricatorUser $user) {
|
||||||
|
$this->user = $user;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function abbreviate($w) {
|
||||||
|
return phutil_utf8_shorten($w, 60);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function render() {
|
||||||
|
require_celerity_resource('ponder-feed-view-css');
|
||||||
|
|
||||||
|
$user = $this->user;
|
||||||
|
$answer = $this->answer;
|
||||||
|
$question = $answer->getQuestion();
|
||||||
|
$author_phid = $question->getAuthorPHID();
|
||||||
|
$handles = $this->handles;
|
||||||
|
|
||||||
|
$votecount =
|
||||||
|
'<div class="ponder-summary-votes">'.
|
||||||
|
phutil_escape_html($answer->getVoteCount()).
|
||||||
|
'<div class="ponder-question-label">'.
|
||||||
|
'votes'.
|
||||||
|
'</div>'.
|
||||||
|
'</div>';
|
||||||
|
|
||||||
|
$title =
|
||||||
|
'<h2 class="ponder-question-title">'.
|
||||||
|
phutil_render_tag(
|
||||||
|
'a',
|
||||||
|
array(
|
||||||
|
"href" => id(new PhutilURI('/Q' . $question->getID()))
|
||||||
|
->setFragment('A' . $answer->getID())
|
||||||
|
),
|
||||||
|
phutil_escape_html('A' . $answer->getID() . ' ' .
|
||||||
|
self::abbreviate($answer->getContent())
|
||||||
|
)
|
||||||
|
).
|
||||||
|
'</h2>';
|
||||||
|
|
||||||
|
$rhs =
|
||||||
|
'<div class="ponder-metadata">'.
|
||||||
|
$title.
|
||||||
|
'<span class="ponder-small-metadata">'.
|
||||||
|
phutil_escape_html(
|
||||||
|
'answer to "'. self::abbreviate($question->getTitle()). '" on ' .
|
||||||
|
phabricator_datetime($answer->getDateCreated(), $user)
|
||||||
|
).
|
||||||
|
'</span>'.
|
||||||
|
'</div>';
|
||||||
|
|
||||||
|
$summary =
|
||||||
|
'<div class="ponder-answer-summary">'.
|
||||||
|
$votecount.
|
||||||
|
$rhs.
|
||||||
|
'</div>';
|
||||||
|
|
||||||
|
return $summary;
|
||||||
|
}
|
||||||
|
}
|
149
src/applications/ponder/view/PonderCommentBodyView.php
Normal file
149
src/applications/ponder/view/PonderCommentBodyView.php
Normal file
|
@ -0,0 +1,149 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2012 Facebook, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
final class PonderCommentBodyView extends AphrontView {
|
||||||
|
|
||||||
|
private $target;
|
||||||
|
private $question;
|
||||||
|
private $handles;
|
||||||
|
private $preview;
|
||||||
|
private $anchorName;
|
||||||
|
private $user;
|
||||||
|
private $action;
|
||||||
|
|
||||||
|
public function setQuestion($question) {
|
||||||
|
$this->question = $question;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setTarget($target) {
|
||||||
|
$this->target = $target;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setAction($action) {
|
||||||
|
$this->action = $action;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setHandles(array $handles) {
|
||||||
|
assert_instances_of($handles, 'PhabricatorObjectHandle');
|
||||||
|
$this->handles = $handles;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setPreview($preview) {
|
||||||
|
$this->preview = $preview;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setUser(PhabricatorUser $user) {
|
||||||
|
$this->user = $user;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function render() {
|
||||||
|
|
||||||
|
if (!$this->user) {
|
||||||
|
throw new Exception("Call setUser() before rendering!");
|
||||||
|
}
|
||||||
|
|
||||||
|
require_celerity_resource('phabricator-remarkup-css');
|
||||||
|
require_celerity_resource('ponder-post-css');
|
||||||
|
|
||||||
|
$user = $this->user;
|
||||||
|
$question = $this->question;
|
||||||
|
$target = $this->target;
|
||||||
|
$content = $target->getContent();
|
||||||
|
$info = array();
|
||||||
|
|
||||||
|
|
||||||
|
$content = PhabricatorMarkupEngine::renderOneObject(
|
||||||
|
$target,
|
||||||
|
$target->getMarkupField());
|
||||||
|
|
||||||
|
$content =
|
||||||
|
'<div class="phabricator-remarkup">'.
|
||||||
|
$content.
|
||||||
|
'</div>';
|
||||||
|
|
||||||
|
$author = $this->handles[$target->getAuthorPHID()];
|
||||||
|
$actions = array($author->renderLink().' '.$this->action);
|
||||||
|
$author_link = $author->renderLink();
|
||||||
|
$xaction_view = id(new PhabricatorTransactionView())
|
||||||
|
->setUser($user)
|
||||||
|
->setImageURI($author->getImageURI())
|
||||||
|
->setContentSource($target->getContentSource())
|
||||||
|
->setActions($actions);
|
||||||
|
|
||||||
|
if ($this->target instanceof PonderAnswer) {
|
||||||
|
$xaction_view->addClass("ponder-answer");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$xaction_view->addClass("ponder-question");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->preview) {
|
||||||
|
$xaction_view->setIsPreview($this->preview);
|
||||||
|
} else {
|
||||||
|
$xaction_view->setEpoch($target->getDateCreated());
|
||||||
|
if ($this->target instanceof PonderAnswer) {
|
||||||
|
$anchor_text = 'Q' . $question->getID(). '#A' . $target->getID();
|
||||||
|
$xaction_view->setAnchor('A'.$target->getID(), $anchor_text);
|
||||||
|
$xaction_view->addClass("ponder-answer");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$xaction_view->appendChild(
|
||||||
|
'<div class="ponder-post-core">'.
|
||||||
|
$content.
|
||||||
|
'</div>'
|
||||||
|
);
|
||||||
|
|
||||||
|
$outerview = $xaction_view;
|
||||||
|
if (!$this->preview) {
|
||||||
|
$outerview =
|
||||||
|
id(new PonderVotableView())
|
||||||
|
->setPHID($target->getPHID())
|
||||||
|
->setCount($target->getVoteCount())
|
||||||
|
->setVote($target->getUserVote());
|
||||||
|
|
||||||
|
if ($this->target instanceof PonderAnswer) {
|
||||||
|
$outerview->setURI('/ponder/answer/vote/');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$outerview->setURI('/ponder/question/vote/');
|
||||||
|
}
|
||||||
|
|
||||||
|
$outerview->appendChild($xaction_view);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $outerview->render();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function renderHandleList(array $phids) {
|
||||||
|
$result = array();
|
||||||
|
foreach ($phids as $phid) {
|
||||||
|
$result[] = $this->handles[$phid]->renderLink();
|
||||||
|
}
|
||||||
|
return implode(', ', $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
72
src/applications/ponder/view/PonderQuestionDetailView.php
Normal file
72
src/applications/ponder/view/PonderQuestionDetailView.php
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2012 Facebook, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
final class PonderQuestionDetailView extends AphrontView {
|
||||||
|
|
||||||
|
private $question;
|
||||||
|
private $user;
|
||||||
|
private $handles;
|
||||||
|
|
||||||
|
public function setQuestion($question) {
|
||||||
|
$this->question = $question;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setUser($user) {
|
||||||
|
$this->user = $user;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setHandles($handles) {
|
||||||
|
$this->handles = $handles;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function render() {
|
||||||
|
require_celerity_resource('ponder-core-view-css');
|
||||||
|
|
||||||
|
$question = $this->question;
|
||||||
|
$handles = $this->handles;
|
||||||
|
$user = $this->user;
|
||||||
|
|
||||||
|
$panel = id(new AphrontPanelView())
|
||||||
|
->addClass("ponder-panel")
|
||||||
|
->setHeader($this->renderObjectLink().' '.$question->getTitle());
|
||||||
|
|
||||||
|
$contentview = new PonderCommentBodyView();
|
||||||
|
$contentview
|
||||||
|
->setTarget($question)
|
||||||
|
->setQuestion($question)
|
||||||
|
->setUser($user)
|
||||||
|
->setHandles($handles)
|
||||||
|
->setAction(PonderConstants::ASKED_LITERAL);
|
||||||
|
|
||||||
|
$panel->appendChild($contentview);
|
||||||
|
|
||||||
|
return $panel->render();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function renderObjectLink() {
|
||||||
|
return phutil_render_tag(
|
||||||
|
'a',
|
||||||
|
array('href' => '/Q' . $this->question->getID()),
|
||||||
|
"Q". phutil_escape_html($this->question->getID())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
102
src/applications/ponder/view/PonderQuestionFeedView.php
Normal file
102
src/applications/ponder/view/PonderQuestionFeedView.php
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2012 Facebook, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
final class PonderQuestionFeedView extends AphrontView {
|
||||||
|
private $user;
|
||||||
|
private $offset;
|
||||||
|
private $data;
|
||||||
|
private $pagesize;
|
||||||
|
private $uri;
|
||||||
|
private $param;
|
||||||
|
|
||||||
|
public function setUser(PhabricatorUser $user) {
|
||||||
|
$this->user = $user;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setOffset($offset) {
|
||||||
|
$this->offset = $offset;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setData($data) {
|
||||||
|
$this->data = $data;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setPageSize($pagesize) {
|
||||||
|
$this->pagesize = $pagesize;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setHandles($handles) {
|
||||||
|
$this->handles = $handles;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setURI($uri, $param) {
|
||||||
|
$this->uri = $uri;
|
||||||
|
$this->param = $param;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function render() {
|
||||||
|
require_celerity_resource('ponder-core-view-css');
|
||||||
|
require_celerity_resource('ponder-feed-view-css');
|
||||||
|
|
||||||
|
$user = $this->user;
|
||||||
|
$offset = $this->offset;
|
||||||
|
$data = $this->data;
|
||||||
|
$handles = $this->handles;
|
||||||
|
$uri = $this->uri;
|
||||||
|
$param = $this->param;
|
||||||
|
$pagesize = $this->pagesize;
|
||||||
|
|
||||||
|
$panel = id(new AphrontPanelView())
|
||||||
|
->setHeader("Popular Questions")
|
||||||
|
->addClass("ponder-panel");
|
||||||
|
|
||||||
|
$panel->addButton(
|
||||||
|
phutil_render_tag(
|
||||||
|
'a',
|
||||||
|
array(
|
||||||
|
'href' => "/ponder/question/ask/",
|
||||||
|
'class' => 'green button',
|
||||||
|
),
|
||||||
|
"Ask a question"));
|
||||||
|
|
||||||
|
$pagebuttons = id(new AphrontPagerView())
|
||||||
|
->setPageSize($pagesize)
|
||||||
|
->setOffset($offset)
|
||||||
|
->setURI($uri, $param);
|
||||||
|
|
||||||
|
$data = $pagebuttons->sliceResults($data);
|
||||||
|
|
||||||
|
|
||||||
|
foreach ($data as $question) {
|
||||||
|
$cur = id(new PonderQuestionSummaryView())
|
||||||
|
->setUser($user)
|
||||||
|
->setQuestion($question)
|
||||||
|
->setHandles($handles);
|
||||||
|
$panel->appendChild($cur);
|
||||||
|
}
|
||||||
|
|
||||||
|
$panel->appendChild($pagebuttons);
|
||||||
|
return $panel->render();
|
||||||
|
}
|
||||||
|
}
|
105
src/applications/ponder/view/PonderQuestionSummaryView.php
Normal file
105
src/applications/ponder/view/PonderQuestionSummaryView.php
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2012 Facebook, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
final class PonderQuestionSummaryView extends AphrontView {
|
||||||
|
private $user;
|
||||||
|
private $question;
|
||||||
|
private $handles;
|
||||||
|
|
||||||
|
public function setQuestion($question) {
|
||||||
|
$this->question = $question;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setHandles($handles) {
|
||||||
|
$this->handles = $handles;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setUser(PhabricatorUser $user) {
|
||||||
|
$this->user = $user;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function render() {
|
||||||
|
require_celerity_resource('ponder-feed-view-css');
|
||||||
|
|
||||||
|
$user = $this->user;
|
||||||
|
$question = $this->question;
|
||||||
|
$author_phid = $question->getAuthorPHID();
|
||||||
|
$handles = $this->handles;
|
||||||
|
|
||||||
|
$authorlink = $handles[$author_phid]
|
||||||
|
->renderLink();
|
||||||
|
|
||||||
|
$votecount =
|
||||||
|
'<div class="ponder-summary-votes">'.
|
||||||
|
phutil_escape_html($question->getVoteCount()).
|
||||||
|
'<div class="ponder-question-label">'.
|
||||||
|
'votes'.
|
||||||
|
'</div>'.
|
||||||
|
'</div>';
|
||||||
|
|
||||||
|
$answerclass = "ponder-summary-answers";
|
||||||
|
if ($question->getAnswercount() == 0) {
|
||||||
|
$answerclass .= " ponder-not-answered";
|
||||||
|
}
|
||||||
|
$answercount =
|
||||||
|
'<div class="ponder-summary-answers">'.
|
||||||
|
phutil_escape_html($question->getAnswerCount()).
|
||||||
|
'<div class="ponder-question-label">'.
|
||||||
|
'answers'.
|
||||||
|
'</div>'.
|
||||||
|
'</div>';
|
||||||
|
|
||||||
|
|
||||||
|
$title =
|
||||||
|
'<h2 class="ponder-question-title">'.
|
||||||
|
phutil_render_tag(
|
||||||
|
'a',
|
||||||
|
array(
|
||||||
|
"href" => '/Q' . $question->getID(),
|
||||||
|
),
|
||||||
|
phutil_escape_html(
|
||||||
|
'Q' . $question->getID() .
|
||||||
|
' ' . $question->getTitle()
|
||||||
|
)
|
||||||
|
) .
|
||||||
|
'</h2>';
|
||||||
|
|
||||||
|
$rhs =
|
||||||
|
'<div class="ponder-metadata">'.
|
||||||
|
$title.
|
||||||
|
'<span class="ponder-small-metadata">'.
|
||||||
|
'asked on '.
|
||||||
|
phabricator_datetime($question->getDateCreated(), $user).
|
||||||
|
' by ' . $authorlink.
|
||||||
|
'</span>'.
|
||||||
|
'</div>';
|
||||||
|
|
||||||
|
$summary =
|
||||||
|
'<div class="ponder-question-summary">'.
|
||||||
|
$votecount.
|
||||||
|
$answercount.
|
||||||
|
$rhs.
|
||||||
|
'</div>';
|
||||||
|
|
||||||
|
|
||||||
|
return $summary;
|
||||||
|
}
|
||||||
|
}
|
159
src/applications/ponder/view/PonderUserProfileView.php
Normal file
159
src/applications/ponder/view/PonderUserProfileView.php
Normal file
|
@ -0,0 +1,159 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2012 Facebook, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
final class PonderUserProfileView extends AphrontView {
|
||||||
|
private $user;
|
||||||
|
private $questionoffset;
|
||||||
|
private $answeroffset;
|
||||||
|
private $questions;
|
||||||
|
private $answers;
|
||||||
|
private $pagesize;
|
||||||
|
private $uri;
|
||||||
|
private $qparam;
|
||||||
|
private $aparam;
|
||||||
|
|
||||||
|
public function setUser(PhabricatorUser $user) {
|
||||||
|
$this->user = $user;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setQuestionOffset($offset) {
|
||||||
|
$this->questionoffset = $offset;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setAnswerOffset($offset) {
|
||||||
|
$this->answeroffset = $offset;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setQuestions($data) {
|
||||||
|
$this->questions = $data;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setAnswers($data) {
|
||||||
|
$this->answers = $data;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setPageSize($pagesize) {
|
||||||
|
$this->pagesize = $pagesize;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setHandles($handles) {
|
||||||
|
$this->handles = $handles;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setURI($uri, $qparam, $aparam) {
|
||||||
|
$this->uri = $uri;
|
||||||
|
$this->qparam = $qparam;
|
||||||
|
$this->aparam = $aparam;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function render() {
|
||||||
|
require_celerity_resource('ponder-core-view-css');
|
||||||
|
require_celerity_resource('ponder-feed-view-css');
|
||||||
|
|
||||||
|
$user = $this->user;
|
||||||
|
$qoffset = $this->questionoffset;
|
||||||
|
$aoffset = $this->answeroffset;
|
||||||
|
$questions = $this->questions;
|
||||||
|
$answers = $this->answers;
|
||||||
|
$handles = $this->handles;
|
||||||
|
$uri = $this->uri;
|
||||||
|
$qparam = $this->qparam;
|
||||||
|
$aparam = $this->aparam;
|
||||||
|
$pagesize = $this->pagesize;
|
||||||
|
|
||||||
|
|
||||||
|
// display questions
|
||||||
|
$question_panel = id(new AphrontPanelView())
|
||||||
|
->setHeader("Your Questions")
|
||||||
|
->addClass("ponder-panel");
|
||||||
|
|
||||||
|
$question_panel->addButton(
|
||||||
|
phutil_render_tag(
|
||||||
|
'a',
|
||||||
|
array(
|
||||||
|
'href' => "/ponder/question/ask/",
|
||||||
|
'class' => 'green button',
|
||||||
|
),
|
||||||
|
"Ask a question"));
|
||||||
|
|
||||||
|
$qpagebuttons = id(new AphrontPagerView())
|
||||||
|
->setPageSize($pagesize)
|
||||||
|
->setOffset($qoffset)
|
||||||
|
->setURI(
|
||||||
|
$uri->alter(
|
||||||
|
$aparam,
|
||||||
|
$aoffset),
|
||||||
|
$qparam);
|
||||||
|
|
||||||
|
$questions = $qpagebuttons->sliceResults($questions);
|
||||||
|
|
||||||
|
foreach ($questions as $question) {
|
||||||
|
$cur = id(new PonderQuestionSummaryView())
|
||||||
|
->setUser($user)
|
||||||
|
->setQuestion($question)
|
||||||
|
->setHandles($handles);
|
||||||
|
$question_panel->appendChild($cur);
|
||||||
|
}
|
||||||
|
|
||||||
|
$question_panel->appendChild($qpagebuttons);
|
||||||
|
|
||||||
|
// display answers
|
||||||
|
$answer_panel = id(new AphrontPanelView())
|
||||||
|
->setHeader("Your Answers")
|
||||||
|
->addClass("ponder-panel")
|
||||||
|
->appendChild(
|
||||||
|
phutil_render_tag(
|
||||||
|
'a',
|
||||||
|
array('id' => 'answers'),
|
||||||
|
"")
|
||||||
|
);
|
||||||
|
|
||||||
|
$apagebuttons = id(new AphrontPagerView())
|
||||||
|
->setPageSize($pagesize)
|
||||||
|
->setOffset($aoffset)
|
||||||
|
->setURI(
|
||||||
|
$uri
|
||||||
|
->alter(
|
||||||
|
$qparam,
|
||||||
|
$qoffset)
|
||||||
|
->setFragment("answers"),
|
||||||
|
$aparam);
|
||||||
|
|
||||||
|
$answers = $apagebuttons->sliceResults($answers);
|
||||||
|
|
||||||
|
foreach ($answers as $answer) {
|
||||||
|
$cur = id(new PonderAnswerSummaryView())
|
||||||
|
->setUser($user)
|
||||||
|
->setAnswer($answer)
|
||||||
|
->setHandles($handles);
|
||||||
|
$answer_panel->appendChild($cur);
|
||||||
|
}
|
||||||
|
|
||||||
|
$answer_panel->appendChild($apagebuttons);
|
||||||
|
|
||||||
|
return $question_panel->render() . $answer_panel->render();
|
||||||
|
}
|
||||||
|
}
|
70
src/applications/ponder/view/PonderVotableView.php
Normal file
70
src/applications/ponder/view/PonderVotableView.php
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2012 Facebook, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
final class PonderVotableView extends AphrontView {
|
||||||
|
|
||||||
|
private $phid;
|
||||||
|
private $uri;
|
||||||
|
private $count;
|
||||||
|
private $vote;
|
||||||
|
|
||||||
|
public function setPHID($phid) {
|
||||||
|
$this->phid = $phid;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setURI($uri) {
|
||||||
|
$this->uri = $uri;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setCount($count) {
|
||||||
|
$this->count = $count;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setVote($vote) {
|
||||||
|
$this->vote = $vote;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function render() {
|
||||||
|
require_celerity_resource('ponder-vote-css');
|
||||||
|
require_celerity_resource('javelin-behavior-ponder-votebox');
|
||||||
|
|
||||||
|
Javelin::initBehavior(
|
||||||
|
'ponder-votebox',
|
||||||
|
array(
|
||||||
|
'nodeid' => $this->phid,
|
||||||
|
'vote' => $this->vote,
|
||||||
|
'count' => $this->count,
|
||||||
|
'uri' => $this->uri
|
||||||
|
));
|
||||||
|
|
||||||
|
$content =
|
||||||
|
'<div class="ponder-votable">'.
|
||||||
|
'<div id="'.phutil_escape_html($this->phid).'" class="ponder-votebox">
|
||||||
|
</div>'.
|
||||||
|
$this->renderChildren().
|
||||||
|
'<div class="ponder-votable-bottom"></div>'.
|
||||||
|
'</div>';
|
||||||
|
|
||||||
|
return $content;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -26,6 +26,7 @@ final class PhabricatorSearchScope {
|
||||||
const SCOPE_OPEN_TASKS = 'open-tasks';
|
const SCOPE_OPEN_TASKS = 'open-tasks';
|
||||||
const SCOPE_COMMITS = 'commits';
|
const SCOPE_COMMITS = 'commits';
|
||||||
const SCOPE_WIKI = 'wiki';
|
const SCOPE_WIKI = 'wiki';
|
||||||
|
const SCOPE_QUESTIONS = 'questions';
|
||||||
|
|
||||||
public static function getScopeOptions() {
|
public static function getScopeOptions() {
|
||||||
return array(
|
return array(
|
||||||
|
@ -34,6 +35,7 @@ final class PhabricatorSearchScope {
|
||||||
self::SCOPE_WIKI => 'Wiki Documents',
|
self::SCOPE_WIKI => 'Wiki Documents',
|
||||||
self::SCOPE_OPEN_REVISIONS => 'Open Revisions',
|
self::SCOPE_OPEN_REVISIONS => 'Open Revisions',
|
||||||
self::SCOPE_COMMITS => 'Commits',
|
self::SCOPE_COMMITS => 'Commits',
|
||||||
|
self::SCOPE_QUESTIONS => 'Ponder Questions',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,7 @@ final class PhabricatorSearchAbstractDocument {
|
||||||
PhabricatorPHIDConstants::PHID_TYPE_TASK => 'Maniphest Tasks',
|
PhabricatorPHIDConstants::PHID_TYPE_TASK => 'Maniphest Tasks',
|
||||||
PhabricatorPHIDConstants::PHID_TYPE_WIKI => 'Phriction Documents',
|
PhabricatorPHIDConstants::PHID_TYPE_WIKI => 'Phriction Documents',
|
||||||
PhabricatorPHIDConstants::PHID_TYPE_USER => 'Phabricator Users',
|
PhabricatorPHIDConstants::PHID_TYPE_USER => 'Phabricator Users',
|
||||||
|
PhabricatorPHIDConstants::PHID_TYPE_QUES => 'Ponder Questions',
|
||||||
) + $more;
|
) + $more;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,11 @@ final class PhabricatorEdgeConfig extends PhabricatorEdgeConstants {
|
||||||
const TYPE_COMMIT_HAS_PROJECT = 15;
|
const TYPE_COMMIT_HAS_PROJECT = 15;
|
||||||
const TYPE_PROJECT_HAS_COMMIT = 16;
|
const TYPE_PROJECT_HAS_COMMIT = 16;
|
||||||
|
|
||||||
|
const TYPE_QUESTION_HAS_VOTING_USER = 17;
|
||||||
|
const TYPE_VOTING_USER_HAS_QUESTION = 18;
|
||||||
|
const TYPE_ANSWER_HAS_VOTING_USER = 19;
|
||||||
|
CONST TYPE_VOTING_USER_HAS_ANSWER = 20;
|
||||||
|
|
||||||
const TYPE_TEST_NO_CYCLE = 9000;
|
const TYPE_TEST_NO_CYCLE = 9000;
|
||||||
|
|
||||||
public static function getInverse($edge_type) {
|
public static function getInverse($edge_type) {
|
||||||
|
@ -71,6 +76,12 @@ final class PhabricatorEdgeConfig extends PhabricatorEdgeConstants {
|
||||||
self::TYPE_COMMIT_HAS_PROJECT => self::TYPE_PROJECT_HAS_COMMIT,
|
self::TYPE_COMMIT_HAS_PROJECT => self::TYPE_PROJECT_HAS_COMMIT,
|
||||||
self::TYPE_PROJECT_HAS_COMMIT => self::TYPE_COMMIT_HAS_PROJECT,
|
self::TYPE_PROJECT_HAS_COMMIT => self::TYPE_COMMIT_HAS_PROJECT,
|
||||||
|
|
||||||
|
self::TYPE_QUESTION_HAS_VOTING_USER =>
|
||||||
|
self::TYPE_VOTING_USER_HAS_QUESTION,
|
||||||
|
self::TYPE_VOTING_USER_HAS_QUESTION =>
|
||||||
|
self::TYPE_QUESTION_HAS_VOTING_USER,
|
||||||
|
self::TYPE_ANSWER_HAS_VOTING_USER => self::TYPE_VOTING_USER_HAS_ANSWER,
|
||||||
|
self::TYPE_VOTING_USER_HAS_ANSWER => self::TYPE_ANSWER_HAS_VOTING_USER,
|
||||||
);
|
);
|
||||||
|
|
||||||
return idx($map, $edge_type);
|
return idx($map, $edge_type);
|
||||||
|
@ -98,6 +109,8 @@ final class PhabricatorEdgeConfig extends PhabricatorEdgeConstants {
|
||||||
PhabricatorPHIDConstants::PHID_TYPE_TOBJ => 'HarbormasterObject',
|
PhabricatorPHIDConstants::PHID_TYPE_TOBJ => 'HarbormasterObject',
|
||||||
PhabricatorPHIDConstants::PHID_TYPE_BLOG => 'PhameBlog',
|
PhabricatorPHIDConstants::PHID_TYPE_BLOG => 'PhameBlog',
|
||||||
PhabricatorPHIDConstants::PHID_TYPE_POST => 'PhamePost',
|
PhabricatorPHIDConstants::PHID_TYPE_POST => 'PhamePost',
|
||||||
|
PhabricatorPHIDConstants::PHID_TYPE_QUES => 'PonderQuestion',
|
||||||
|
PhabricatorPHIDConstants::PHID_TYPE_ANSW => 'PonderAnswer',
|
||||||
);
|
);
|
||||||
|
|
||||||
$class = idx($class_map, $phid_type);
|
$class = idx($class_map, $phid_type);
|
||||||
|
|
|
@ -330,6 +330,11 @@ final class PhabricatorMarkupEngine {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static function newPonderMarkupEngine(array $options = array()) {
|
||||||
|
return self::newMarkupEngine($options);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @task engine
|
* @task engine
|
||||||
*/
|
*/
|
||||||
|
@ -406,6 +411,8 @@ final class PhabricatorMarkupEngine {
|
||||||
$rules[] = new PhabricatorRemarkupRuleManiphest();
|
$rules[] = new PhabricatorRemarkupRuleManiphest();
|
||||||
$rules[] = new PhabricatorRemarkupRulePaste();
|
$rules[] = new PhabricatorRemarkupRulePaste();
|
||||||
|
|
||||||
|
$rules[] = new PonderRuleQuestion();
|
||||||
|
|
||||||
if ($options['macros']) {
|
if ($options['macros']) {
|
||||||
$rules[] = new PhabricatorRemarkupRuleImageMacro();
|
$rules[] = new PhabricatorRemarkupRuleImageMacro();
|
||||||
}
|
}
|
||||||
|
|
29
src/infrastructure/markup/rule/PonderRuleQuestion.php
Normal file
29
src/infrastructure/markup/rule/PonderRuleQuestion.php
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2012 Facebook, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group markup
|
||||||
|
*/
|
||||||
|
final class PonderRuleQuestion
|
||||||
|
extends PhabricatorRemarkupRuleObjectName {
|
||||||
|
|
||||||
|
protected function getObjectNamePrefix() {
|
||||||
|
return 'Q';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -163,6 +163,10 @@ final class PhabricatorBuiltinPatchList extends PhabricatorSQLPatchList {
|
||||||
'type' => 'db',
|
'type' => 'db',
|
||||||
'name' => 'fact',
|
'name' => 'fact',
|
||||||
),
|
),
|
||||||
|
'db.ponder' => array(
|
||||||
|
'type' => 'db',
|
||||||
|
'name' => 'ponder',
|
||||||
|
),
|
||||||
'0000.legacy.sql' => array(
|
'0000.legacy.sql' => array(
|
||||||
'type' => 'sql',
|
'type' => 'sql',
|
||||||
'name' => $this->getPatchPath('0000.legacy.sql'),
|
'name' => $this->getPatchPath('0000.legacy.sql'),
|
||||||
|
@ -952,6 +956,10 @@ final class PhabricatorBuiltinPatchList extends PhabricatorSQLPatchList {
|
||||||
'type' => 'sql',
|
'type' => 'sql',
|
||||||
'name' => $this->getPatchPath('fact-raw.sql'),
|
'name' => $this->getPatchPath('fact-raw.sql'),
|
||||||
),
|
),
|
||||||
|
'ponder.sql' => array(
|
||||||
|
'type' => 'sql',
|
||||||
|
'name' => $this->getPatchPath('ponder.sql')
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
25
webroot/rsrc/css/application/ponder/core.css
Normal file
25
webroot/rsrc/css/application/ponder/core.css
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
/**
|
||||||
|
* @provides ponder-core-view-css
|
||||||
|
*/
|
||||||
|
|
||||||
|
.ponder-primary-pane {
|
||||||
|
margin: 0 0 0 2em;
|
||||||
|
padding-bottom: 2em;
|
||||||
|
max-width: 800px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ponder-panel {
|
||||||
|
max-width: 800px;
|
||||||
|
font-family : antiqua, verdana, arial;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ponder-panel h1 {
|
||||||
|
padding-bottom: 8px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
font-size : 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ponder-panel .aphront-form-view {
|
||||||
|
border : none;
|
||||||
|
background : none;
|
||||||
|
}
|
74
webroot/rsrc/css/application/ponder/feed.css
Normal file
74
webroot/rsrc/css/application/ponder/feed.css
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
/**
|
||||||
|
* @provides ponder-feed-view-css
|
||||||
|
*/
|
||||||
|
|
||||||
|
.ponder-question-summary {
|
||||||
|
width : 100%;
|
||||||
|
background : #DFDFE3;
|
||||||
|
float : left;
|
||||||
|
clear : both;
|
||||||
|
margin-top : 1px;
|
||||||
|
padding : 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ponder-answer-summary {
|
||||||
|
width : 100%;
|
||||||
|
background : #DFDFE3;
|
||||||
|
float : left;
|
||||||
|
clear : both;
|
||||||
|
margin-top : 1px;
|
||||||
|
padding : 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ponder-summary-votes {
|
||||||
|
width : 50px;
|
||||||
|
height : 36pt;
|
||||||
|
font-size : 18pt;
|
||||||
|
text-align : center;
|
||||||
|
background : #EEE;
|
||||||
|
border : 1px solid #BBB;
|
||||||
|
float : left;
|
||||||
|
margin : 2px;
|
||||||
|
padding-top : 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ponder-summary-answers {
|
||||||
|
width : 50px;
|
||||||
|
height : 36pt;
|
||||||
|
font-size : 18pt;
|
||||||
|
text-align : center;
|
||||||
|
background : #EEE;
|
||||||
|
border : 1px solid #BBB;
|
||||||
|
float : left;
|
||||||
|
margin : 2px;
|
||||||
|
padding-top : 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ponder-question-label {
|
||||||
|
font-size : 6pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2.ponder-question-title {
|
||||||
|
font-size : 12pt;
|
||||||
|
margin : 2px;
|
||||||
|
padding : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2.ponder-answer-title {
|
||||||
|
font-size : 12pt;
|
||||||
|
margin : 2px;
|
||||||
|
padding : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ponder-metadata {
|
||||||
|
padding-left : 5px;
|
||||||
|
width : 650px;
|
||||||
|
float : left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ponder-small-metadata {
|
||||||
|
font-size : 7.5pt;
|
||||||
|
color : #555;
|
||||||
|
margin : 0;
|
||||||
|
text-align : right;
|
||||||
|
}
|
34
webroot/rsrc/css/application/ponder/post.css
Normal file
34
webroot/rsrc/css/application/ponder/post.css
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
/**
|
||||||
|
* @provides ponder-post-css
|
||||||
|
*/
|
||||||
|
|
||||||
|
.ponder-post-list {
|
||||||
|
max-width: 1162px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ponder-add-answer-panel {
|
||||||
|
max-width: 1162px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ponder-post-list .anchor-target {
|
||||||
|
background-color: #ffffdd;
|
||||||
|
border-color: #ffff00;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ponder-post-core .phabricator-remarkup .remarkup-code-block {
|
||||||
|
width: 88ex;
|
||||||
|
width: 81ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
.phabricator-transaction-view .ponder-question {
|
||||||
|
border-color: #777;
|
||||||
|
}
|
||||||
|
|
||||||
|
.phabricator-transaction-detail .ponder-question {
|
||||||
|
border-color: #777;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.phabricator-transaction-view .ponder-answer {
|
||||||
|
/* border-color: #203791; */
|
||||||
|
}
|
74
webroot/rsrc/css/application/ponder/vote.css
Normal file
74
webroot/rsrc/css/application/ponder/vote.css
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
/**
|
||||||
|
* @provides ponder-vote-css
|
||||||
|
*/
|
||||||
|
|
||||||
|
.ponder-votable {
|
||||||
|
min-height : 120px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ponder-votable .phabricator-transaction-detail {
|
||||||
|
min-height : 90px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ponder-votebox {
|
||||||
|
float : left;
|
||||||
|
width : 32px;
|
||||||
|
height : 60px;
|
||||||
|
margin-top : 56px;
|
||||||
|
margin-left : 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ponder-upbutton {
|
||||||
|
border : none;
|
||||||
|
padding : 0;
|
||||||
|
margin : 0;
|
||||||
|
width : 32px;
|
||||||
|
height : 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ponder-downbutton {
|
||||||
|
border : none;
|
||||||
|
padding : 0;
|
||||||
|
margin : 0;
|
||||||
|
width : 32px;
|
||||||
|
height : 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ponder-votecount {
|
||||||
|
width : 32px;
|
||||||
|
height : 22pt;
|
||||||
|
padding : 0;
|
||||||
|
margin : 0;
|
||||||
|
overflow : visible;
|
||||||
|
text-align : center;
|
||||||
|
font-size : 15pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ponder-upbutton:hover {
|
||||||
|
cursor : pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ponder-downbutton:hover {
|
||||||
|
cursor : pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ponder-votable-bottom {
|
||||||
|
clear : both;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ponder-upbutton {
|
||||||
|
background : url(/rsrc/image/application/ponder/upvote.png) 0 -13px no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ponder-upbutton.ponder-vote-up {
|
||||||
|
background : url(/rsrc/image/application/ponder/upvote.png) 0 0 no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ponder-downbutton {
|
||||||
|
background : url(/rsrc/image/application/ponder/downvote.png)
|
||||||
|
0 -13px no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ponder-downbutton.ponder-vote-down {
|
||||||
|
background : url(/rsrc/image/application/ponder/downvote.png) 0 0 no-repeat;
|
||||||
|
}
|
BIN
webroot/rsrc/image/app/app_ponder.png
Normal file
BIN
webroot/rsrc/image/app/app_ponder.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.5 KiB |
BIN
webroot/rsrc/image/application/ponder/downvote.png
Normal file
BIN
webroot/rsrc/image/application/ponder/downvote.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 929 B |
BIN
webroot/rsrc/image/application/ponder/upvote.png
Normal file
BIN
webroot/rsrc/image/application/ponder/upvote.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 916 B |
|
@ -0,0 +1,32 @@
|
||||||
|
/**
|
||||||
|
* @provides javelin-behavior-ponder-feedback-preview
|
||||||
|
* @requires javelin-behavior
|
||||||
|
* javelin-dom
|
||||||
|
* javelin-util
|
||||||
|
* phabricator-shaped-request
|
||||||
|
*/
|
||||||
|
|
||||||
|
JX.behavior('ponder-feedback-preview', function(config) {
|
||||||
|
|
||||||
|
var content = JX.$(config.content);
|
||||||
|
var question_id = config.question_id;
|
||||||
|
|
||||||
|
var callback = function(r) {
|
||||||
|
JX.DOM.setContent(JX.$(config.preview), JX.$H(r));
|
||||||
|
};
|
||||||
|
|
||||||
|
var getdata = function() {
|
||||||
|
var data = {
|
||||||
|
content : content.value,
|
||||||
|
question_id : question_id
|
||||||
|
};
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
var request = new JX.PhabricatorShapedRequest(config.uri, callback, getdata);
|
||||||
|
var trigger = JX.bind(request, request.trigger);
|
||||||
|
|
||||||
|
JX.DOM.listen(content, 'keydown', null, trigger);
|
||||||
|
|
||||||
|
request.start();
|
||||||
|
});
|
76
webroot/rsrc/js/application/ponder/behavior-votebox.js
Normal file
76
webroot/rsrc/js/application/ponder/behavior-votebox.js
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
/**
|
||||||
|
* @provides javelin-behavior-ponder-votebox
|
||||||
|
* @requires javelin-behavior
|
||||||
|
* javelin-dom
|
||||||
|
* javelin-util
|
||||||
|
* phabricator-shaped-request
|
||||||
|
*/
|
||||||
|
|
||||||
|
JX.behavior('ponder-votebox', function(config) {
|
||||||
|
|
||||||
|
var node = JX.$(config.nodeid);
|
||||||
|
var vote = config.vote;
|
||||||
|
var count = config.count | 0;
|
||||||
|
var targetURI = config.targetURI;
|
||||||
|
|
||||||
|
var upnode, countnode, downnode;
|
||||||
|
|
||||||
|
// this defines the behavior of the up/downvote
|
||||||
|
// buttons, e.g. clicking 'up' transitions from
|
||||||
|
// an 'up' vote to a 'none' vote
|
||||||
|
var votecycle = {
|
||||||
|
"1" : { up : "0", down : "-1" },
|
||||||
|
"0" : { up : "1", down : "-1" },
|
||||||
|
"-1" : { up : "1", down : "0" }
|
||||||
|
};
|
||||||
|
|
||||||
|
var voteclass = {
|
||||||
|
"0" : "ponder-vote-none",
|
||||||
|
"-1" : "ponder-vote-down",
|
||||||
|
"1" : "ponder-vote-up"
|
||||||
|
};
|
||||||
|
|
||||||
|
function decorate() {
|
||||||
|
upnode = JX.$N('div');
|
||||||
|
countnode = JX.$N('div');
|
||||||
|
downnode = JX.$N('div');
|
||||||
|
node.appendChild(upnode);
|
||||||
|
node.appendChild(countnode);
|
||||||
|
node.appendChild(downnode);
|
||||||
|
JX.DOM.alterClass(upnode, "ponder-upbutton " + voteclass[vote], true);
|
||||||
|
JX.DOM.alterClass(downnode, "ponder-downbutton " + voteclass[vote], true);
|
||||||
|
JX.DOM.alterClass(countnode, "ponder-votecount", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function update_state() {
|
||||||
|
upnode.className = "ponder-upbutton " + voteclass[vote];
|
||||||
|
downnode.className = "ponder-downbutton " + voteclass[vote];
|
||||||
|
JX.DOM.setContent(countnode, JX.$H(count.toString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
function getdata() {
|
||||||
|
return { phid : config.nodeid, vote : vote };
|
||||||
|
}
|
||||||
|
|
||||||
|
var request = new JX.PhabricatorShapedRequest(config.uri, JX.id, getdata);
|
||||||
|
var trigger = JX.bind(request, request.trigger);
|
||||||
|
|
||||||
|
function handle_upvote(e) {
|
||||||
|
count += votecycle[vote].up - vote;
|
||||||
|
vote = votecycle[vote].up;
|
||||||
|
trigger();
|
||||||
|
update_state();
|
||||||
|
}
|
||||||
|
|
||||||
|
function handle_downvote(e) {
|
||||||
|
count += votecycle[vote].down - vote;
|
||||||
|
vote = votecycle[vote].down;
|
||||||
|
trigger();
|
||||||
|
update_state();
|
||||||
|
}
|
||||||
|
|
||||||
|
decorate();
|
||||||
|
update_state();
|
||||||
|
JX.DOM.listen(upnode, 'click', null, handle_upvote);
|
||||||
|
JX.DOM.listen(downnode, 'click', null, handle_downvote);
|
||||||
|
});
|
Loading…
Add table
Reference in a new issue