Skip to content

Commit ac72722

Browse files
authored
Merge pull request #97 from topcoder-platform/develop
v1.7
2 parents f340419 + 1391113 commit ac72722

File tree

2 files changed

+196
-11
lines changed

2 files changed

+196
-11
lines changed

Topcoder/class.topcoder.plugin.php

Lines changed: 193 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ class TopcoderPlugin extends Gdn_Plugin {
3333
const CACHE_KEY_TOPCODER_PROFILE = 'topcoder.{UserID}';
3434
const CACHE_TOPCODER_KEY_TOPCODER_PROFILE = 'topcoder.{Handle}';
3535
const CACHE_TOPCODER_KEY_TOPCODER_ROLE_RESOURCES = 'topcoder.roleresources';
36+
const CACHE_TOPCODER_KEY_TOPCODER_CHALLENGE = 'topcoder.challenge.{ChallengeID}';
3637
const CACHE_TOPCODER_KEY_TOPCODER_CHALLENGE_RESOURCES = 'topcoder.challenge.{ChallengeID}.resources';
3738

3839
const CACHE_DEFAULT_EXPIRY_TIME = 60*60*3; //The default expiration time in Memcached is in seconds, 10800 = 3 hours
@@ -866,6 +867,7 @@ function gdn_dispatcher_beforeControllerMethod_handler($sender, $args){
866867
]);
867868

868869
$groupID = false;
870+
$categoryModel = new CategoryModel();
869871
if($args['Controller'] instanceof DiscussionController) {
870872
if(array_key_exists('discussionid', $methodArgs)) {
871873
$discussionID = $methodArgs['discussionid'];
@@ -887,7 +889,6 @@ function gdn_dispatcher_beforeControllerMethod_handler($sender, $args){
887889
$discussionModel = new DiscussionModel();
888890
$discussion = $discussionModel->getID($discussionID);
889891
if($discussion->CategoryID){
890-
$categoryModel = new CategoryModel();
891892
$category = $categoryModel->getID($discussion->CategoryID);
892893
$groupID = $category->GroupID;
893894
}
@@ -898,16 +899,28 @@ function gdn_dispatcher_beforeControllerMethod_handler($sender, $args){
898899
$discussionModel = new DiscussionModel();
899900
$discussion = $discussionModel->getID($comment->DiscussionID);
900901
if($discussion->CategoryID){
901-
$categoryModel = new CategoryModel();
902902
$category = $categoryModel->getID($discussion->CategoryID);
903903
$groupID = $category->GroupID;
904904
}
905905
}
906+
} else if($args['Controller'] instanceof CategoriesController) {
907+
if (array_key_exists('categoryidentifier', $methodArgs)) {
908+
$categoryUrlCode = $methodArgs['categoryidentifier'];
909+
if($categoryUrlCode) {
910+
$category = $categoryModel->getByCode($categoryUrlCode);
911+
$groupID = val('GroupID', $category);
912+
}
913+
}
906914
}
907915

908916
if($groupID && $groupID > 0) {
909917
$groupModel = new GroupModel();
910918
$group = $groupModel->getByGroupID($groupID);
919+
$category = $categoryModel->getByCode($group->ChallengeID);
920+
$categoryID= val('CategoryID', $category);
921+
Gdn::controller()->setData('Breadcrumbs.Options.GroupCategoryID', $categoryID);
922+
Gdn::controller()->setData('Breadcrumbs.Options.GroupID', $groupID);
923+
Gdn::controller()->setData('Breadcrumbs.Options.ChallengeID', $group->ChallengeID);
911924
if ($group->ChallengeID) {
912925
$this->setTopcoderProjectData($args['Controller'], $group->ChallengeID);
913926
}
@@ -1446,11 +1459,11 @@ public function getChallengeResources($challengeId) {
14461459
}
14471460

14481461
$expirationTime = self::CACHE_DEFAULT_EXPIRY_TIME;
1449-
$challenge = self::loadChallenge($challengeId);
1450-
if($challenge && count($challenge) > 0) {
1462+
$challenge = self::getChallenge($challengeId);
1463+
if($challenge) {
14511464
// Set expiration time for Challenge roles
1452-
$endDate = strtotime($challenge[0]->endDate);
1453-
$startDate = strtotime($challenge[0]->startDate);
1465+
$endDate = $challenge['EndDate'];
1466+
$startDate =$challenge['StartDate'];
14541467
// $duration = $endDate > -1 && $startDate > -1 ? $endDate - $startDate: 0;
14551468
// archived
14561469
$isEnded = $endDate > -1 && now() - $endDate > 0;
@@ -1520,6 +1533,44 @@ private static function loadChallengeResources($challengeId) {
15201533
return null;
15211534
}
15221535

1536+
/**
1537+
* Get Topcoder Challenge by ChallengeId
1538+
* @param $challengeId
1539+
* @return mixed|null
1540+
*/
1541+
public function getChallenge($challengeId) {
1542+
$challenge = self::getChallengeFromCache($challengeId);
1543+
if ($challenge) {
1544+
return $challenge;
1545+
}
1546+
1547+
$cachedChallenge = ['ChallengeID' => $challengeId];
1548+
$challenge = self::loadChallenge($challengeId);
1549+
1550+
$expirationTime = self::CACHE_DEFAULT_EXPIRY_TIME;
1551+
if($challenge) {
1552+
// Set expiration time for Challenge roles
1553+
$startDate = strtotime($challenge->startDate);
1554+
$endDate = strtotime($challenge->endDate);
1555+
// archived
1556+
$isEnded = $endDate > -1 && now() - $endDate > 0;
1557+
if(!$isEnded) {
1558+
$expirationTime = self::CACHE_ONE_DAY_EXPIRY_TIME;
1559+
}
1560+
$cachedChallenge['StartDate'] = $startDate;
1561+
$cachedChallenge['EndDate'] = $endDate;
1562+
$cachedChallenge['Track'] = $challenge->track;
1563+
$termIDs = array_column($challenge->terms, 'id');
1564+
$NDA_UUID = c('Plugins.Topcoder.NDA_UUID');
1565+
$cachedChallenge['IsNDA'] = in_array($NDA_UUID, $termIDs);
1566+
}
1567+
if (Gdn_Cache::activeEnabled()) {
1568+
self::topcoderChallengeCache($challengeId, $cachedChallenge, $expirationTime);
1569+
}
1570+
return $cachedChallenge;
1571+
}
1572+
1573+
15231574
/**
15241575
* Load Topcoder Challenge by Challenge ID
15251576
* @param $challengeId
@@ -1535,7 +1586,7 @@ private static function loadChallenge($challengeId) {
15351586
'header' => 'Authorization: Bearer ' .$token
15361587
));
15371588
$context = stream_context_create($options);
1538-
$data = file_get_contents($topcoderChallengeApiUrl . '?challengeId=' . $challengeId, false, $context);
1589+
$data = file_get_contents($topcoderChallengeApiUrl . $challengeId, false, $context);
15391590
if ($data === false) {
15401591
// Handle errors (e.g. 404 and others)
15411592
self::log('Couldn\'t get challenge: no token', ['headers'=> json_encode($http_response_header)]);
@@ -1549,6 +1600,35 @@ private static function loadChallenge($challengeId) {
15491600
return null;
15501601
}
15511602

1603+
/**
1604+
* Load challenge from cache
1605+
* @param $challengeID
1606+
* @return false|mixed
1607+
*/
1608+
private static function getChallengeFromCache($challengeID) {
1609+
if(!Gdn_Cache::activeEnabled()) {
1610+
return false;
1611+
}
1612+
1613+
$handleKey = formatString(self::CACHE_TOPCODER_KEY_TOPCODER_CHALLENGE, ['ChallengeID' => $challengeID]);
1614+
if(!Gdn::cache()->exists($handleKey)) {
1615+
return false;
1616+
}
1617+
$challenge = Gdn::cache()->get($handleKey);
1618+
if ($challenge === Gdn_Cache::CACHEOP_FAILURE) {
1619+
return false;
1620+
}
1621+
return $challenge;
1622+
}
1623+
1624+
private static function topcoderChallengeCache($challengeID, $challenge, $expirationTime = self::CACHE_DEFAULT_EXPIRY_TIME) {
1625+
$challengeKey = formatString(self::CACHE_TOPCODER_KEY_TOPCODER_CHALLENGE, ['ChallengeID' => $challengeID]);
1626+
return Gdn::cache()->store($challengeKey , $challenge, [
1627+
Gdn_Cache::FEATURE_EXPIRY => $expirationTime
1628+
]);
1629+
}
1630+
1631+
15521632
/**
15531633
* Get a Topcoder Roles
15541634
*
@@ -1761,13 +1841,15 @@ public static function getUserPhotoUrl($user) {
17611841
// Set Topcoder Project Roles Data for a challenge
17621842
private function setTopcoderProjectData($sender, $challengeID) {
17631843
if($challengeID) {
1844+
$challenge = $this->getChallenge($challengeID);
17641845
$resources = $this->getChallengeResources($challengeID);
17651846
$roleResources = $this->getRoleResources();
17661847
$currentProjectRoles = $this->getTopcoderProjectRoles(Gdn::session()->User, $resources, $roleResources);
17671848
if($currentProjectRoles) {
17681849
$currentProjectRoles = array_map('strtolower',$currentProjectRoles);
17691850
}
17701851

1852+
$sender->Data['Challenge'] = $challenge;
17711853
$sender->Data['ChallengeResources'] = $resources;
17721854
$sender->Data['ChallengeRoleResources'] = $roleResources;
17731855
$sender->Data['ChallengeCurrentUserProjectRoles'] = $currentProjectRoles;
@@ -1777,7 +1859,7 @@ private function setTopcoderProjectData($sender, $challengeID) {
17771859
// }
17781860
self::log('setTopcoderProjectData', ['ChallengeID' => $challengeID, 'currentUser' => $currentProjectRoles,
17791861
'Topcoder Resources' => $resources , 'Topcoder RoleResources'
1780-
=> $roleResources,]);
1862+
=> $roleResources, 'challenge' =>$challenge]);
17811863
}
17821864
}
17831865

@@ -1984,6 +2066,62 @@ public static function log($message, $data = []) {
19842066
);
19852067
}
19862068
}
2069+
2070+
// MAGIC EVENTS TO OVERRIDE VANILLA CONTROLLER METHODS
2071+
2072+
/**
2073+
* Allows user to announce or unannounce a discussion.
2074+
* FIX: https://github.com/topcoder-platform/forums/issues/456
2075+
* @param int $discussionID Unique discussion ID.
2076+
* @param string $TransientKey Single-use hash to prove intent.
2077+
*/
2078+
public function discussionController_announce_create($sender, $discussionID = '', $announce=true ,$target = '') {
2079+
// Make sure we are posting back.
2080+
if (!$sender->Request->isAuthenticatedPostBack()) {
2081+
throw permissionException('Javascript');
2082+
}
2083+
2084+
$discussion = $sender->DiscussionModel->getID($discussionID);
2085+
if (!$discussion) {
2086+
throw notFoundException('Discussion');
2087+
}
2088+
2089+
//$sender->categoryPermission($discussion->CategoryID, 'Vanilla.Discussions.Announce');// protected
2090+
if (!CategoryModel::checkPermission($discussion->CategoryID, 'Vanilla.Discussions.Announce')) {
2091+
$sender->permission('Vanilla.Discussions.Announce', true, 'Category', $discussion->CategoryID);
2092+
}
2093+
2094+
// Save the property.
2095+
// 0 - Don't Announce Discussion
2096+
// 2 - Announce Discussion in the current category
2097+
$newAnnounceValue = (bool)$announce? 2 : 0;
2098+
$sender->DiscussionModel->setField($discussionID, 'Announce', $newAnnounceValue);
2099+
$discussion->Announce = $newAnnounceValue;
2100+
2101+
// Redirect to the front page
2102+
if ($sender->_DeliveryType === DELIVERY_TYPE_ALL) {
2103+
$target = getIncomingValue('Target', 'discussions');
2104+
redirectTo($target);
2105+
}
2106+
2107+
$sender->sendOptions($discussion);
2108+
if ($newAnnounceValue == 2) {
2109+
require_once $sender->fetchViewLocation('helper_functions', 'Discussions', 'vanilla');
2110+
$dataHtml = tag($discussion, 'Announce', 'Announcement');
2111+
// Remove if exists
2112+
$sender->jsonTarget(".Section-DiscussionList #Discussion_$discussionID .Meta-Discussion", $dataHtml , 'Prepend');
2113+
$sender->jsonTarget(".Section-DiscussionList #Discussion_$discussionID", 'Announcement', 'AddClass');
2114+
} else {
2115+
$sender->jsonTarget(".Section-DiscussionList #Discussion_$discussionID .Tag-Announcement", null, 'Remove');
2116+
$sender->jsonTarget(".Section-DiscussionList #Discussion_$discussionID", 'Announcement', 'RemoveClass');
2117+
2118+
}
2119+
2120+
$sender->jsonTarget("#Discussion_$discussionID", null, 'Highlight');
2121+
$sender->jsonTarget(".Discussion #Item_0", null, 'Highlight');
2122+
2123+
$sender->render('Blank', 'Utility', 'Dashboard');
2124+
}
19872125
}
19882126

19892127
if(!function_exists('topcoderRatingCssClass')) {
@@ -2483,3 +2621,50 @@ function topcoderMentionAnchor($mention, $cssClass = null, $options = null) {
24832621
}
24842622
}
24852623

2624+
if (!function_exists('watchingSorts')) {
2625+
/**
2626+
* Returns watching sorting.
2627+
*
2628+
* @param string $extraClasses any extra classes you add to the drop down
2629+
* @return string
2630+
*/
2631+
function watchingSorts($extraClasses = '') {
2632+
if (!Gdn::session()->isValid()) {
2633+
return;
2634+
}
2635+
2636+
$baseUrl = preg_replace('/\?.*/', '', Gdn::request()->getFullPath());
2637+
$transientKey = Gdn::session()->transientKey();
2638+
$filters = [
2639+
[
2640+
'name' => t('New'),
2641+
'param' => 'sort',
2642+
'value' => 'new',
2643+
'extra' => ['TransientKey' => $transientKey, 'save' => 1]
2644+
],
2645+
2646+
[
2647+
'name' => t('Old'),
2648+
'param' => 'sort',
2649+
'value' => 'old',
2650+
'extra' => ['TransientKey' => $transientKey, 'save' => 1]
2651+
]
2652+
];
2653+
2654+
$defaultParams = [];
2655+
if (!empty($defaultParams)) {
2656+
$defaultUrl = $baseUrl.'?'.http_build_query($defaultParams);
2657+
} else {
2658+
$defaultUrl = $baseUrl;
2659+
}
2660+
2661+
return sortsDropDown('WatchingSort',
2662+
$baseUrl,
2663+
$filters,
2664+
$extraClasses,
2665+
null,
2666+
$defaultUrl,
2667+
'Sort'
2668+
);
2669+
}
2670+
}

Topcoder/controllers/class.watchingcontroller.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,10 @@ public function index($cp = '', $dp = '') {
5656
$sort = Gdn::request()->get('sort', null);
5757
$saveSorting = $sort !== null && Gdn::request()->get('save') && Gdn::session()->validateTransientKey(Gdn::request()->get('TransientKey', ''));
5858
if($saveSorting) {
59-
Gdn::session()->setPreference('CategorySort', $sort);
59+
Gdn::session()->setPreference('WatchingSort', $sort);
6060
}
61-
$sort = Gdn::session()->getPreference('CategorySort', false);
62-
$this->setData('CategorySort', $sort);
61+
$sort = Gdn::session()->getPreference('WatchingSort', false);
62+
$this->setData('WatchingSort', $sort);
6363

6464
$userMetaModel = new UserMetaModel();
6565
list($cp, $categoryLimit) = offsetLimit($cp, 30);

0 commit comments

Comments
 (0)