@@ -284,6 +284,8 @@ public function gdn_auth_startAuthenticator_handler() {
284
284
if (!c ('Garden.Installed ' )) {
285
285
return ;
286
286
}
287
+ self ::log ('Embedded Settings ' , ['Garden.Embed.Allow ' => c ('Garden.Embed.Allow ' )]);
288
+
287
289
self ::log ('Cache ' , ['Active Cache ' => Gdn_Cache::activeCache (), 'Type ' =>Gdn::cache ()->type ()]);
288
290
289
291
if (!$ this ->isDefault ()) {
@@ -895,7 +897,7 @@ function gdn_dispatcher_beforeControllerMethod_handler($sender, $args){
895
897
}
896
898
} else if ($ args ['Controller ' ] instanceof GroupController) {
897
899
if (array_key_exists ('groupid ' , $ methodArgs )) {
898
- $ groupID = ( int ) $ methodArgs ['groupid ' ];
900
+ $ groupID = self :: convertToGroupID ( $ methodArgs ['groupid ' ]) ;
899
901
}
900
902
} else if ($ args ['Controller ' ] instanceof PostController) {
901
903
if (array_key_exists ('discussionid ' , $ methodArgs )) {
@@ -932,19 +934,68 @@ function gdn_dispatcher_beforeControllerMethod_handler($sender, $args){
932
934
$ group = $ groupModel ->getByGroupID ($ groupID );
933
935
$ category = $ categoryModel ->getByCode ($ group ->ChallengeID );
934
936
$ categoryID = val ('CategoryID ' , $ category );
935
- Gdn::controller ()->setData ('Breadcrumbs.Options.GroupCategoryID ' , $ categoryID );
936
- Gdn::controller ()->setData ('Breadcrumbs.Options.GroupID ' , $ groupID );
937
- Gdn::controller ()->setData ('Breadcrumbs.Options.ChallengeID ' , $ group ->ChallengeID );
937
+ $ controller = $ args ['Controller ' ];
938
+ $ controller ->setData ('BreadcrumbsOptionsGroupCategoryID ' , $ categoryID );
939
+ $ controller ->setData ('BreadcrumbsOptionsGroupID ' , $ groupID );
940
+ $ controller ->setData ('BreadcrumbsOptionsChallengeID ' , $ group ->ChallengeID );
938
941
if ($ group ->ChallengeID ) {
939
- $ this ->setTopcoderProjectData ($ args [ ' Controller ' ] , $ group ->ChallengeID );
942
+ $ this ->setTopcoderProjectData ($ controller , $ group ->ChallengeID );
940
943
}
941
944
}
942
945
}
943
946
947
+ private static function convertToGroupID ($ id ) {
948
+ if (is_numeric ($ id ) && $ id > 0 ) {
949
+ return $ id ;
950
+ }
951
+
952
+ if (self ::isValidUuid ($ id ) === true ) {
953
+ $ categoryModel = new CategoryModel ();
954
+ $ category = $ categoryModel ->getByCode ($ id );
955
+ return val ('GroupID ' , $ category , 0 );
956
+ }
957
+
958
+ return 0 ;
959
+ }
960
+
961
+ private static function isValidUuid ($ uuid ) {
962
+ if (!is_string ($ uuid )) {
963
+ return false ;
964
+ }
965
+ if (!\preg_match ('/^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}$/ ' , $ uuid )) {
966
+ return false ;
967
+ }
968
+ return true ;
969
+ }
970
+
971
+ public function base_beforeBuildBreadcrumbs_handler ($ sender , $ args ) {
972
+ if (Gdn::session ()->isValid ()) {
973
+ $ showFullBreadcrumbs = & $ args ['ShowFullBreadcrumbs ' ];
974
+ //FIX Issues-652: Client Manager - no navigation when embedded
975
+ $ showFullBreadcrumbs = !hideInMFE ();
976
+ }
977
+ }
944
978
/**
945
979
* Add scripts. Add script to hide iPhone browser bar on pageload.
946
980
*/
947
981
public function base_render_before ($ sender ) {
982
+ if (isset ($ _SERVER ['HTTP_REFERER ' ])) {
983
+ $ url = $ _SERVER ['HTTP_REFERER ' ];
984
+ parse_str ( parse_url ( $ url , PHP_URL_QUERY ), $ array );
985
+ $ embedType = $ array ['mbed_type ' ];
986
+ if ($ embedType == 'mfe ' ) {
987
+ $ sender ->addDefinition ('MFEEmbedded ' , '1 ' );
988
+ $ sender ->MasterView = 'mfe ' ;
989
+ // logMessage(__FILE__,__LINE__,'TopcoderPlugin','base_render_before',"Use Embed Master Template due to HTTP_REFERER".$url);
990
+ }
991
+ }
992
+
993
+ // Force view options
994
+ if (getIncomingValue ('embed_type ' ) == 'mfe ' ) {
995
+ $ sender ->addDefinition ('MFEEmbedded ' , '1 ' );
996
+ $ sender ->MasterView = 'mfe ' ;
997
+ // logMessage(__FILE__,__LINE__,'TopcoderPlugin','base_render_before',"Use Embed Master Template due to Query Param");
998
+ }
948
999
if (is_object ($ sender ->Head )) {
949
1000
$ sender ->Head ->addString ($ this ->getJS ());
950
1001
}
@@ -1574,6 +1625,7 @@ public function getChallenge($challengeId) {
1574
1625
$ cachedChallenge ['StartDate ' ] = $ startDate ;
1575
1626
$ cachedChallenge ['EndDate ' ] = $ endDate ;
1576
1627
$ cachedChallenge ['Track ' ] = $ challenge ->track ;
1628
+ $ cachedChallenge ['IsSelfService ' ] = $ challenge ->legacy ->selfService ;
1577
1629
$ termIDs = array_column ($ challenge ->terms , 'id ' );
1578
1630
$ NDA_UUID = c ('Plugins.Topcoder.NDA_UUID ' );
1579
1631
$ cachedChallenge ['IsNDA ' ] = in_array ($ NDA_UUID , $ termIDs );
@@ -1750,6 +1802,39 @@ private static function isTopcoderAdmin($topcoderRoles = false) {
1750
1802
return false ;
1751
1803
}
1752
1804
1805
+ /**
1806
+ * Check if the list of Topcoder roles includes 'Client Manager' role
1807
+ * @return bool true, if the list of Topcoder roles includes 'Client Manager'
1808
+ */
1809
+ public static function isTopcoderClientManager () {
1810
+ if (!Gdn::session ()->isValid ()) {
1811
+ return false ;
1812
+ }
1813
+ $ topcoderRoles = Gdn::controller ()->data ("ChallengeCurrentUserProjectRoles " );
1814
+ if ($ topcoderRoles ) {
1815
+ $ lowerRoleNames = array_map ('strtolower ' , $ topcoderRoles );
1816
+ return count (array_intersect ($ lowerRoleNames , ["client manager " ])) > 0 ;
1817
+ }
1818
+
1819
+ return false ;
1820
+ }
1821
+
1822
+ /**
1823
+ * Check if the challenge has self-service flag
1824
+ * @return bool true, if the challenge has self-service flag
1825
+ */
1826
+ public static function isChallengeSelfService () {
1827
+ if (!Gdn::session ()->isValid ()) {
1828
+ return false ;
1829
+ }
1830
+ $ challenge = Gdn::controller ()->data ("Challenge " );
1831
+ if ($ challenge ) {
1832
+ return $ challenge ['IsSelfService ' ];
1833
+ }
1834
+
1835
+ return false ;
1836
+ }
1837
+
1753
1838
/**
1754
1839
* Get Topcoder Role names
1755
1840
* @param false $topcoderRoles
@@ -1871,7 +1956,7 @@ private function setTopcoderProjectData($sender, $challengeID) {
1871
1956
// if($sender->GroupModel) {
1872
1957
// $sender->GroupModel->setCurrentUserTopcoderProjectRoles($currentProjectRoles);
1873
1958
// }
1874
- self ::log ('setTopcoderProjectData ' , ['ChallengeID ' => $ challengeID , 'currentUser ' => $ currentProjectRoles ,
1959
+ self ::log ('setTopcoderProjectData ' , ['ChallengeID ' => $ challengeID , 'CurrentUserProjectRoles ' => $ currentProjectRoles ,
1875
1960
'Topcoder Resources ' => $ resources , 'Topcoder RoleResources '
1876
1961
=> $ roleResources , 'challenge ' =>$ challenge ]);
1877
1962
}
@@ -1955,11 +2040,21 @@ private static function topcoderUserCache($userFields) {
1955
2040
return $ cached ;
1956
2041
}
1957
2042
1958
- // TODO: Debugging issues-108
2043
+ // Support Micro-frontends forums app
1959
2044
public function gdn_dispatcher_beforeDispatch_handler ($ sender , $ args ) {
1960
- self ::log ('gdn_dispatcher_beforeDispatch_handler ' , [
2045
+ $ mfeUrl = c ("Garden.Embed.RemoteUrl " );
2046
+ $ isEmbedded = (bool ) c ('Garden.Embed.Allow ' , false );
2047
+
2048
+ $ data = array (
2049
+ 'Garden.Embed.Allow ' => $ isEmbedded ,
2050
+ 'MFEUrl ' => $ mfeUrl ,
2051
+ 'Request(current fullPath) ' => Gdn::request ()->getFullPath (),
2052
+ 'Request(pathAndQuery) ' => Gdn::request ()->pathAndQuery (),
2053
+ 'Request(Method) ' => Gdn::request ()->getMethod (),
1961
2054
'Permissions ' => Gdn::session ()->getPermissionsArray (),
1962
- ]);
2055
+ );
2056
+ // logMessage(__FILE__, __LINE__, 'TopcoderPlugin', "Data", json_encode($data ));
2057
+ // self::log('gdn_dispatcher_beforeDispatch_handler', $data);
1963
2058
}
1964
2059
1965
2060
// Topcoder Cache is used for caching Topcoder Users by handle.
@@ -2293,6 +2388,103 @@ public function profileController_preferences_create($sender, $userReference = '
2293
2388
$ sender ->_setBreadcrumbs ($ sender ->data ('Title ' ), $ sender ->canonicalUrl ());
2294
2389
$ sender ->render ();
2295
2390
}
2391
+
2392
+ // All notified users have been added in an activity. This called before adding an activity in an activity Queue and sending+saving it in DB
2393
+ public function activityModel_BeforeCheckPreference_handler ($ sender , $ args ) {
2394
+ $ activity = &$ args ['Data ' ];
2395
+ $ notifyUserID = val ('NotifyUserID ' , $ activity );
2396
+ $ userModel = new UserModel ();
2397
+ $ user = $ userModel ->getID ($ notifyUserID );
2398
+ $ data = $ activity ['Data ' ];
2399
+ $ challengeID = $ data ['ChallengeID ' ];
2400
+ if ($ challengeID ) {
2401
+ $ activityType = $ activity ['RecordType ' ];
2402
+ if ($ activityType == 'Discussion ' || $ activityType == 'Comment ' ) {
2403
+ $ resources = $ this ->getChallengeResources ($ challengeID );
2404
+ $ roleResources = $ this ->getRoleResources ();
2405
+ $ currentProjectRoles = $ this ->getTopcoderProjectRoles ($ user , $ resources , $ roleResources );
2406
+ if ($ currentProjectRoles ) {
2407
+ $ currentProjectRoles = array_map ('strtolower ' , $ currentProjectRoles );
2408
+ $ isClientManager = count (array_intersect ($ currentProjectRoles , ["client manager " ])) > 0 ;
2409
+ if ($ isClientManager ) {
2410
+ $ recordID = $ activity ['RecordID ' ];
2411
+ $ category = CategoryModel::categories ($ challengeID );
2412
+ $ categoryName = val ('Name ' , $ category );
2413
+ $ userModel = new UserModel ();
2414
+ $ discussionModel = new DiscussionModel ();
2415
+ if ($ activityType == 'Discussion ' ) {
2416
+ $ discussion = $ discussionModel ->getID ($ recordID );
2417
+ $ message = Gdn::formatService ()->renderQuote (val ('Body ' , $ discussion ), val ('Format ' , $ discussion ));
2418
+ $ author = $ userModel ->getID (val ('InsertUserID ' , $ discussion ));
2419
+ $ dateInserted = Gdn_Format::dateFull (val ('DateInserted ' ,$ discussion ));
2420
+ // $categoryBreadcrumbs = array_column(array_values(CategoryModel::getAncestors(val('CategoryID',$discussion))), 'Name');
2421
+
2422
+ $ activity ['Story ' ] =
2423
+ '<p>Hi there,</p> ' .
2424
+ '<p>A new message has been posted on the discussion tied to your Topcoder Work " ' . $ categoryName . '" ' .
2425
+ 'which was updated ' . $ dateInserted . ' by ' . $ author ->Name . ':<p/> ' .
2426
+ '<hr/> ' .
2427
+ '<div style="padding: 0; margin: 0"> ' .
2428
+ '<p><span>Discussion: ' . val ('Name ' , $ discussion ) . '</p> ' .
2429
+ '<p><span>Author: ' . val ('Name ' , $ author ) . '</p> ' .
2430
+ // '<p><span>Category: ' . implode('›', $categoryBreadcrumbs) . '</p>' .
2431
+ '<p><span>Message:</span> ' . $ message . '</p> ' .
2432
+ '<hr/> ' .
2433
+ '<p>To answer, click "Open Discussion" below to be taken to this discussion.<br/>
2434
+ Please do not reply to this email.<br/>
2435
+ Thank you!
2436
+ The Topcoder Team</p> ' .
2437
+ '</div> ' .
2438
+ '<hr/> ' ;
2439
+
2440
+ } else { // Comment
2441
+ $ commentModel = new CommentModel ();
2442
+ $ comment = $ commentModel ->getID ($ recordID );
2443
+ // $discussion = $discussionModel->getID(val('DiscussionID', $comment));
2444
+ // $discussionName = val('Name',$discussion);
2445
+ $ commentDateInserted = Gdn_Format::dateFull (val ('DateInserted ' ,$ comment ));
2446
+ $ commentAuthor = $ userModel ->getID (val ('InsertUserID ' ,$ comment ));
2447
+ $ commentStory = Gdn::formatService ()->renderQuote (val ('Body ' ,$ comment ), val ('Format ' ,$ comment ));
2448
+ $ activity ['Story ' ] =
2449
+ '<p>Hi there,</p> ' .
2450
+ '<p>A new message has been posted on the discussion tied to your Topcoder Work " ' . $ categoryName . '" ' .
2451
+ 'which was updated ' . $ commentDateInserted . ' by ' . val ('Name ' ,$ commentAuthor ) . ':</p> ' .
2452
+ '<hr/> ' .
2453
+ '<p class="label"><span style="display: block">Message:</span> ' .'</p> ' .
2454
+ $ commentStory .
2455
+ '<br/><hr/> ' ;
2456
+
2457
+ $ parentCommentID = (int )val ('ParentCommentID ' ,$ comment );
2458
+ if ($ parentCommentID > 0 ) {
2459
+ $ parentComment = $ commentModel ->getID ($ parentCommentID , DATASET_TYPE_ARRAY );
2460
+ $ parentCommentAuthor = $ userModel ->getID ($ parentComment ['InsertUserID ' ]);
2461
+ $ parentCommentStory = condense (Gdn_Format::to ($ parentComment ['Body ' ], $ parentComment ['Format ' ]));
2462
+ $ activity ['Story ' ] .=
2463
+ '<p class="label">Original Message (by ' .$ parentCommentAuthor ->Name .' ):</p> ' .
2464
+ '<p> ' .
2465
+ $ parentCommentStory .
2466
+ '</p> ' .
2467
+ '<hr/> ' ;
2468
+ }
2469
+ $ activity ['Story ' ] .= '<p>To answer, click "Open Discussion" below to be taken to this discussion.<br/>
2470
+ Please do not reply to this email.<br/>
2471
+ Thank you!
2472
+ The Topcoder Team</p> ' ;
2473
+ }
2474
+
2475
+ $ headline = 'Message From a Topcoder Member on Your Work - Please See ' ;
2476
+ $ activity ['HeadlineFormat ' ] = $ headline ;
2477
+ $ activity ['Headline ' ] = $ headline ;
2478
+ $ activity ['Data ' ]['EmailUrl ' ] = val ('EmbedUrl ' , $ data );
2479
+ $ activity ['Data ' ]['EmailTemplate ' ] = 'email-selfservice ' ;
2480
+ return ;
2481
+ }
2482
+ }
2483
+ }
2484
+ }
2485
+ $ activity ['Data ' ]['EmailUrl ' ] = externalUrl (val ('Route ' , $ activity ) == '' ? '/ ' : val ('Route ' , $ activity ));
2486
+ $ activity ['Data ' ]['EmailTemplate ' ] = 'email-basic ' ;
2487
+ }
2296
2488
}
2297
2489
2298
2490
if (!function_exists ('topcoderRatingCssClass ' )) {
@@ -2436,9 +2628,11 @@ function userPhoto($user, $options = []) {
2436
2628
}
2437
2629
2438
2630
$ isTopcoderAdmin = val ('IsAdmin ' , $ topcoderProfile );
2631
+ $ isTopcoderClientManager = TopcoderPlugin::isTopcoderClientManager ();
2439
2632
$ photoUrl = isset ($ photoUrl ) && !empty (trim ($ photoUrl )) ? $ photoUrl : UserModel::getDefaultAvatarUrl ();
2440
2633
$ isUnlickableUser = TopcoderPlugin::isUnclickableUser ($ name );
2441
- $ href = (val ('NoLink ' , $ options )) || $ isUnlickableUser ? '' : ' href=" ' .url ($ userLink ).'" ' ;
2634
+ $ href = (val ('NoLink ' , $ options )) || $ isUnlickableUser ||
2635
+ ($ isTopcoderClientManager && getIncomingValue ('embed_type ' ) == 'mfe ' ) ? '' : ' href=" ' .url ($ userLink ).'" ' ;
2442
2636
2443
2637
Gdn::controller ()->EventArguments ['User ' ] = $ user ;
2444
2638
Gdn::controller ()->EventArguments ['Title ' ] =& $ title ;
@@ -2527,11 +2721,14 @@ function userAnchor($user, $cssClass = null, $options = null) {
2527
2721
$ attributes ['title ' ] = $ options ['title ' ];
2528
2722
}
2529
2723
2724
+ $ topcoderProfile = TopcoderPlugin::getTopcoderUser ($ userID );
2725
+
2530
2726
// Go to Topcoder user profile link instead of Vanilla profile link
2531
- $ isUnlickableUser = TopcoderPlugin::isUnclickableUser ($ name );
2727
+ $ isTopcoderClientManager = TopcoderPlugin::isTopcoderClientManager ();
2728
+ $ isUnlickableUser = ( $ isTopcoderClientManager && getIncomingValue ('embed_type ' ) == 'mfe ' ) || TopcoderPlugin::isUnclickableUser ($ name );
2532
2729
$ userUrl = $ isUnlickableUser ? '# ' : topcoderUserUrl ($ user , $ px );
2533
2730
2534
- $ topcoderProfile = TopcoderPlugin:: getTopcoderUser ( $ userID );
2731
+
2535
2732
$ topcoderRating = val ('Rating ' ,$ topcoderProfile , false );
2536
2733
if ($ topcoderRating != false || $ topcoderRating == null ) {
2537
2734
$ coderStyles = TopcoderPlugin::getRatingCssClass ($ topcoderRating );
@@ -2838,4 +3035,34 @@ function watchingSorts($extraClasses = '') {
2838
3035
'Sort '
2839
3036
);
2840
3037
}
3038
+ }
3039
+
3040
+ if (!function_exists ('isMFE ' )) {
3041
+ function isMFE () {
3042
+ return getIncomingValue ('embed_type ' ) == 'mfe ' ;
3043
+ }
3044
+ }
3045
+
3046
+ if (!function_exists ('hideInMFE ' )) {
3047
+ function hideInMFE () {
3048
+ if (!Gdn::session ()->isValid ()) {
3049
+ return false ;
3050
+ }
3051
+ //FIX Issues-652: Client Manager - no navigation when embedded
3052
+ $ isMFE = isMFE ();
3053
+ $ isTopcoderClientManager = TopcoderPlugin::isTopcoderClientManager ();
3054
+ if ($ isMFE && $ isTopcoderClientManager ) {
3055
+ return true ;
3056
+ }
3057
+ return false ;
3058
+ }
3059
+ }
3060
+
3061
+ if (!function_exists ('isSelfService ' )) {
3062
+ function isSelfService () {
3063
+ if (!Gdn::session ()->isValid ()) {
3064
+ return false ;
3065
+ }
3066
+ return TopcoderPlugin::isChallengeSelfService ();
3067
+ }
2841
3068
}
0 commit comments