├── .gitignore ├── src ├── views │ └── themes │ │ └── default │ │ ├── design │ │ ├── custom.css │ │ ├── customadmin.css │ │ └── favicon.png │ │ ├── views │ │ ├── discussions │ │ │ ├── sort.php │ │ │ ├── discussion.php │ │ │ ├── mine.php │ │ │ ├── profile.php │ │ │ ├── discussions.php │ │ │ ├── bookmarked.php │ │ │ ├── index_rss.php │ │ │ ├── unread.php │ │ │ ├── archives.php │ │ │ ├── popin.php │ │ │ ├── index.php │ │ │ └── table.php │ │ ├── discussion │ │ │ ├── comment.php │ │ │ ├── profile.php │ │ │ ├── delete.php │ │ │ ├── comments.php │ │ │ ├── announce.php │ │ │ ├── profilecomments.php │ │ │ ├── embed.php │ │ │ ├── index.php │ │ │ └── discussion.php │ │ ├── setup │ │ │ └── index.php │ │ ├── post │ │ │ ├── preview.php │ │ │ ├── spam.php │ │ │ ├── editcomment.php │ │ │ ├── index.php │ │ │ └── discussion.php │ │ ├── modules │ │ │ ├── categorymoderators.php │ │ │ ├── discussion.php │ │ │ ├── newdiscussion.php │ │ │ ├── discussions.php │ │ │ ├── discussionsorter.php │ │ │ ├── drafts.php │ │ │ ├── categoryfollowtoggle.php │ │ │ ├── promotedcontent.php │ │ │ ├── bookmarked.php │ │ │ ├── categories.php │ │ │ ├── discussionfilter.php │ │ │ └── helper_functions.php │ │ ├── moderation │ │ │ ├── confirmcommentdeletes.php │ │ │ ├── confirmdiscussiondeletes.php │ │ │ └── confirmdiscussionmoves.php │ │ ├── drafts │ │ │ ├── index.php │ │ │ └── drafts.php │ │ ├── categories │ │ │ ├── table.php │ │ │ ├── discussions.php │ │ │ └── subtree.php │ │ ├── default.master.tpl │ │ └── settings │ │ │ ├── deletecategory.php │ │ │ ├── notificationpreferences.php │ │ │ ├── addcategory.php │ │ │ └── editcategory.php │ │ ├── about.php │ │ └── README.md ├── config │ ├── views.php │ ├── paths.php │ ├── routes.php │ ├── forum.php │ └── package.php ├── exceptions │ ├── NoVanillaUserMappedToUser.php │ ├── NoVanillaUserMappedToGuest.php │ ├── VanillaForumsContentNotFound.php │ ├── NoVanillaUserMappedToAuthenticatedUser.php │ ├── VanillaForumsRequiresMysqlException.php │ ├── VanillaForumsSetupException.php │ ├── VanillaForumsNotFoundException.php │ └── NotAVanillaForumsAuditColumnException.php ├── models │ ├── NoPrimaryKeyTrait.php │ ├── AnalyticsLocal.php │ ├── Spammer.php │ ├── Role.php │ ├── Session.php │ ├── UserRepository.php │ ├── ActivityType.php │ ├── Ban.php │ ├── RoleRepository.php │ ├── Comment.php │ ├── ActivityComment.php │ ├── Regarding.php │ ├── ConversationMessage.php │ ├── Invitation.php │ ├── Media.php │ ├── Message.php │ ├── Attachment.php │ ├── Permission.php │ ├── Tag.php │ ├── TagDiscussion.php │ ├── BaseModel.php │ ├── Draft.php │ ├── Log.php │ ├── AuditingTrait.php │ ├── Conversation.php │ ├── Activity.php │ ├── Category.php │ ├── Discussion.php │ ├── AuditingObserver.php │ └── User.php ├── boot │ ├── routes.php │ └── helpers.php ├── services │ ├── GardenRequest.php │ ├── GardenDatabase.php │ ├── UserMapperAllGuestAccess.php │ ├── AbstractUserMapper.php │ ├── UserMapperById.php │ ├── UserMapperByClosure.php │ ├── VanillaHelperTrait.php │ ├── UserMapperInterface.php │ ├── GardenPluginManager.php │ ├── UrlGenerator.php │ ├── GardenSmarty.php │ ├── VanillaBootstrap.php │ ├── UserMapperSynchronicity.php │ ├── VanillaRunner.php │ └── VanillaAdapter.php ├── migrations │ ├── 2014_09_23_194713_create_GDN_UserRole_table.php │ ├── 2014_09_23_194713_create_GDN_Spammer_table.php │ ├── 2014_09_23_194713_create_GDN_AnalyticsLocal_table.php │ ├── 2014_09_23_194713_create_GDN_UserMeta_table.php │ ├── 2014_09_23_194713_create_GDN_UserAuthenticationNonce_table.php │ ├── 2014_09_23_194713_create_GDN_UserComment_table.php │ ├── 2014_09_23_194713_create_GDN_UserCategory_table.php │ ├── 2014_09_23_194713_create_GDN_UserAuthentication_table.php │ ├── 2014_09_23_194713_create_GDN_Session_table.php │ ├── 2014_09_23_194713_create_GDN_TagDiscussion_table.php │ ├── 2014_09_23_194713_create_GDN_UserMergeItem_table.php │ ├── 2014_09_23_194713_create_GDN_Role_table.php │ ├── 2014_09_23_194713_create_GDN_ActivityComment_table.php │ ├── 2014_09_23_194713_create_GDN_UserPoints_table.php │ ├── 2014_09_23_194713_create_GDN_UserMerge_table.php │ ├── 2014_09_23_194713_create_GDN_ConversationMessage_table.php │ ├── 2014_09_23_194713_create_GDN_Ban_table.php │ ├── 2014_09_23_194713_create_GDN_ActivityType_table.php │ ├── 2014_09_23_194713_create_GDN_UserAuthenticationToken_table.php │ ├── 2014_09_23_194713_create_GDN_UserDiscussion_table.php │ ├── 2014_09_23_194713_create_GDN_Invitation_table.php │ ├── 2014_09_23_194713_create_GDN_Tag_table.php │ ├── 2014_09_23_194713_create_GDN_Regarding_table.php │ ├── 2014_09_23_194713_create_GDN_Message_table.php │ ├── 2014_09_23_194713_create_GDN_UserConversation_table.php │ ├── 2014_09_23_194713_create_GDN_Draft_table.php │ ├── 2014_09_23_194713_create_GDN_Attachment_table.php │ ├── 2014_09_23_194713_create_GDN_Media_table.php │ ├── 2014_09_23_194713_create_GDN_UserAuthenticationProvider_table.php │ ├── 2014_09_23_194713_create_GDN_Conversation_table.php │ ├── 2014_09_23_194713_create_GDN_Log_table.php │ ├── 2014_09_23_194713_create_GDN_Activity_table.php │ ├── 2014_09_23_194713_create_GDN_Comment_table.php │ ├── 2014_09_23_194713_create_GDN_Category_table.php │ ├── 2014_09_23_194713_create_GDN_User_table.php │ ├── 2014_09_23_194713_create_GDN_Discussion_table.php │ └── 2014_09_23_194713_create_GDN_Permission_table.php ├── controllers │ └── PassthruController.php ├── commands │ ├── VanillaConnect.php │ └── VanillaMigrate.php └── ForumServiceProvider.php ├── phpunit.xml └── composer.json /.gitignore: -------------------------------------------------------------------------------- 1 | composer.phar 2 | vendor 3 | -------------------------------------------------------------------------------- /src/views/themes/default/design/custom.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/views/themes/default/design/customadmin.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/config/views.php: -------------------------------------------------------------------------------- 1 | Vanilla Setup'; 3 | echo $this->Form->Open(); 4 | echo $this->Form->Errors(); 5 | echo $this->Form->Input('Vanilla.Test'); 6 | echo $this->Form->Close('Continue'); -------------------------------------------------------------------------------- /src/models/NoPrimaryKeyTrait.php: -------------------------------------------------------------------------------- 1 | base_path() . '/vendor/bishopb/vanilla', 8 | 9 | /** 10 | * Where do you want uploads to go? 11 | */ 12 | 'uploads' => base_path() . '/uploads', 13 | ]; 14 | -------------------------------------------------------------------------------- /src/views/themes/default/views/discussions/discussion.php: -------------------------------------------------------------------------------- 1 | FetchViewLocation('helper_functions', 'discussions')); 5 | 6 | WriteDiscussion($Discussion, $this, $Session, ''); -------------------------------------------------------------------------------- /src/exceptions/VanillaForumsNotFoundException.php: -------------------------------------------------------------------------------- 1 | 'forum', 11 | ]; 12 | -------------------------------------------------------------------------------- /src/views/themes/default/views/post/preview.php: -------------------------------------------------------------------------------- 1 | FireEvent('BeforeCommentPreviewFormat'); 3 | $this->Comment->Body = Gdn_Format::To($this->Comment->Body, GetValue('Format', $this->Comment, C('Garden.InputFormatter'))); 4 | $this->FireEvent('AfterCommentPreviewFormat'); 5 | ?> 6 |
7 |
Comment->Body; ?>
8 |
-------------------------------------------------------------------------------- /src/models/AnalyticsLocal.php: -------------------------------------------------------------------------------- 1 | 'required|max:8|unique:GDN_AnalyticsLocal', 10 | 'Views' => 'integer', 11 | 'EmbedViews' => 'integer', 12 | ]; 13 | 14 | // definitions 15 | protected $table = 'GDN_AnalyticsLocal'; 16 | use NoPrimaryKeyTrait; 17 | } 18 | -------------------------------------------------------------------------------- /src/views/themes/default/views/modules/categorymoderators.php: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 | 12 |
-------------------------------------------------------------------------------- /src/boot/routes.php: -------------------------------------------------------------------------------- 1 | $prefix ], function () use ($prefix) { 11 | // default all routes through the vanilla passthru 12 | Route::any( 13 | '{slug?}', [ 'uses' => '\BishopB\Forum\PassthruController@index' ] 14 | )->where('slug', '^.*'); 15 | }); 16 | -------------------------------------------------------------------------------- /src/views/themes/default/views/discussion/profile.php: -------------------------------------------------------------------------------- 1 | '; 4 | echo '

'.T('Comments').'

'; 5 | echo ''; 14 | echo ''; -------------------------------------------------------------------------------- /src/models/Spammer.php: -------------------------------------------------------------------------------- 1 | 'integer|min:0', 10 | 'CountDeletedSpam' => 'integer|min:0', 11 | ]; 12 | 13 | // definitions 14 | protected $table = 'GDN_Spammer'; 15 | protected $primaryKey = 'UserID'; 16 | 17 | // relationships 18 | public function user() 19 | { 20 | return $this->hasOne('\BishopB\Forum\User', 'UserID', 'UserID'); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/config/forum.php: -------------------------------------------------------------------------------- 1 | 'Laravel Forums', 14 | 15 | /** 16 | * @param string default-controller 17 | * 18 | * Given no other route components, this is the first page the user sees. 19 | */ 20 | 'default-controller' => 'discussions', 21 | ]; 22 | -------------------------------------------------------------------------------- /src/views/themes/default/about.php: -------------------------------------------------------------------------------- 1 | '+Baseline', 8 | 'Description' => "The default theme for Vanilla. This theme's purpose is to give the bare-minimum of styling on everything except the forum contents. Our goal is for you to take this theme and customize it by adding your own header & footer.", 9 | 'Version' => APPLICATION_VERSION, 10 | 'Author' => "Mark O'Sullivan", 11 | 'AuthorEmail' => 'mark@vanillaforums.com', 12 | 'AuthorUrl' => 'http://markosullivan.ca' 13 | ]; 14 | -------------------------------------------------------------------------------- /src/views/themes/default/views/discussion/delete.php: -------------------------------------------------------------------------------- 1 | 2 | 3 |

Data('Title'); ?>

4 | 5 | Form->Open(); 7 | echo $this->Form->Errors(); 8 | 9 | echo '
'.sprintf(T('Are you sure you want to delete this %s?'), T('discussion')).'
'; 10 | 11 | echo '
'; 12 | echo $this->Form->Button('OK', array('class' => 'Button Primary')); 13 | echo $this->Form->Button('Cancel', array('type' => 'button', 'class' => 'Button Close')); 14 | echo '
'; 15 | echo $this->Form->Close(); 16 | ?> 17 | -------------------------------------------------------------------------------- /src/views/themes/default/views/modules/discussion.php: -------------------------------------------------------------------------------- 1 | Prefix)) { 4 | $this->Prefix = 'Bookmark'; 5 | } 6 | 7 | if (!function_exists('WriteModuleDiscussion')) { 8 | $DiscussionsModule = new DiscussionsModule(); 9 | require_once $DiscussionsModule->FetchViewLocation('helper_functions'); 10 | require_once Gdn::Controller()->FetchViewLocation('helper_functions', 'Discussions', 'Vanilla'); 11 | } 12 | 13 | WriteModuleDiscussion($Discussion, $this->Prefix); -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 15 | ./tests/ 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/views/themes/default/views/discussions/mine.php: -------------------------------------------------------------------------------- 1 | Title(T('My Discussions')); 3 | include($this->FetchViewLocation('helper_functions', 'discussions', 'vanilla')); 4 | $ViewLocation = $this->FetchViewLocation('discussions'); 5 | // WriteFilterTabs($this); 6 | if ($this->DiscussionData->NumRows() > 0) { 7 | echo $this->Pager->ToString('less'); 8 | ?> 9 | 12 | Pager->ToString('more'); 14 | } else { 15 | echo '
'.T('You have not started any discussions.').'
'; 16 | } 17 | -------------------------------------------------------------------------------- /src/views/themes/default/views/modules/newdiscussion.php: -------------------------------------------------------------------------------- 1 | '; 3 | $Text = T('Start a New Discussion', 'New Discussion'); 4 | $UrlCode = GetValue('UrlCode', GetValue('Category', $Data), ''); 5 | $Url = '/post/discussion/'.$UrlCode; 6 | if ($this->QueryString) { 7 | $Url .= (strpos($Url, '?') !== FALSE ? '&' : '?').$this->QueryString; 8 | } 9 | $Css = 'Button Primary Action NewDiscussion'; 10 | $Css .= strpos($this->CssClass, 'Big') !== FALSE ? ' BigButton' : ''; 11 | 12 | echo ButtonGroup($this->Buttons, $Css, $this->DefaultButton); 13 | Gdn::Controller()->FireEvent('AfterNewDiscussionButton'); 14 | 15 | echo '
'; -------------------------------------------------------------------------------- /src/models/Role.php: -------------------------------------------------------------------------------- 1 | 'required|max:100', 10 | 'Description' => 'max:500', 11 | 'Sort' => 'integer', 12 | 'Deletable' => 'boolean', 13 | 'CanSession' => 'boolean', 14 | 'PersonalInfo' => 'boolean', 15 | ]; 16 | 17 | // definitions 18 | protected $table = 'GDN_Role'; 19 | protected $primaryKey = 'RoleID'; 20 | 21 | // relationships 22 | public function permissions() 23 | { 24 | return $this->hasMany('\BishopB\Forum\Permission', 'RoleID', 'RoleID'); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/views/themes/default/views/discussions/profile.php: -------------------------------------------------------------------------------- 1 | '; 4 | echo '

'.T('Discussions').'

'; 5 | echo ''; 17 | echo '
'; -------------------------------------------------------------------------------- /src/views/themes/default/views/discussions/discussions.php: -------------------------------------------------------------------------------- 1 | FetchViewLocation('helper_functions', 'discussions', 'vanilla')); 5 | 6 | $Alt = ''; 7 | if (property_exists($this, 'AnnounceData') && is_object($this->AnnounceData)) { 8 | foreach ($this->AnnounceData->Result() as $Discussion) { 9 | $Alt = $Alt == ' Alt' ? '' : ' Alt'; 10 | WriteDiscussion($Discussion, $this, $Session, $Alt); 11 | } 12 | } 13 | 14 | $Alt = ''; 15 | foreach ($this->DiscussionData->Result() as $Discussion) { 16 | $Alt = $Alt == ' Alt' ? '' : ' Alt'; 17 | WriteDiscussion($Discussion, $this, $Session, $Alt); 18 | } -------------------------------------------------------------------------------- /src/services/GardenRequest.php: -------------------------------------------------------------------------------- 1 | Reset(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/services/GardenDatabase.php: -------------------------------------------------------------------------------- 1 | $Sql, 16 | 'params' => $InputParameters, 17 | 'options' => $Options, 18 | ]); 19 | } 20 | 21 | // defer 22 | $rc = parent::Query($Sql, $InputParameters, $Options); 23 | 24 | // exception? 25 | return $rc; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/views/themes/default/views/modules/discussions.php: -------------------------------------------------------------------------------- 1 | FetchViewLocation('helper_functions'); 3 | 4 | if (!isset($this->Prefix)) 5 | $this->Prefix = 'Discussion'; 6 | ?> 7 |
8 | 9 | 19 |
-------------------------------------------------------------------------------- /src/boot/helpers.php: -------------------------------------------------------------------------------- 1 | handleException($ex); 28 | } 29 | -------------------------------------------------------------------------------- /src/views/themes/default/views/discussion/comments.php: -------------------------------------------------------------------------------- 1 | FireEvent('BeforeCommentsRender'); 5 | if (!function_exists('WriteComment')) 6 | include($this->FetchViewLocation('helper_functions', 'discussion')); 7 | 8 | $CurrentOffset = $this->Offset; 9 | 10 | $this->EventArguments['CurrentOffset'] = &$CurrentOffset; 11 | $this->FireEvent('BeforeFirstComment'); 12 | 13 | // Only prints individual comment list items 14 | $Comments = $this->Data('Comments')->Result(); 15 | foreach ($Comments as $Comment) { 16 | if (is_numeric($Comment->CommentID)) 17 | $CurrentOffset++; 18 | $this->CurrentComment = $Comment; 19 | WriteComment($Comment, $this, $Session, $CurrentOffset); 20 | } 21 | -------------------------------------------------------------------------------- /src/services/UserMapperAllGuestAccess.php: -------------------------------------------------------------------------------- 1 | create_guest_account = function () { 15 | return UserRepository::createWithRoles( 16 | [ 17 | 'UserID' => 1, 18 | 'Name' => 'Anonymous', 19 | 'Password' => str_random(64), 20 | 'HashMethod' => 'random', 21 | ], 22 | [ RoleRepository::member() ] 23 | ); 24 | }; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/views/themes/default/views/modules/discussionsorter.php: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 | SortFieldSelected, $this->SortOptions); 6 | echo Wrap($Text.' '.Sprite('SpMenu', 'Sprite Sprite16'), 'span', array('class' => 'Selected')); 7 | ?> 8 | 18 | 19 |
20 | -------------------------------------------------------------------------------- /src/views/themes/default/views/post/spam.php: -------------------------------------------------------------------------------- 1 | Form->Open(); 3 | echo $this->Form->Errors(); 4 | echo $this->Form->Close(); 5 | ?> 6 |
7 | RequestMethod == 'discussion') 9 | $Message = T('DiscussionRequiresApproval', "Your discussion will appear after it is approved."); 10 | else 11 | $Message = T('CommentRequiresApproval', "Your comment will appear after it is approved."); 12 | echo '
', $Message, '
'; 13 | 14 | if ($this->Data('DiscussionUrl')) 15 | echo '
', sprintf(T('Click here to go back to the discussion.'), Url($this->Data('DiscussionUrl'))), '
'; 16 | else 17 | echo '
', Anchor('Back to the discussions list.', 'discussions'), '
'; 18 | ?> 19 |
-------------------------------------------------------------------------------- /src/models/Session.php: -------------------------------------------------------------------------------- 1 | 'required|max:32', 10 | 'UserID' => 'exists:GDN_User,UserID', 11 | 'TransientKey' => 'required|max:12', 12 | // 'Attributes' => none, 13 | ]; 14 | 15 | // auditing 16 | use AuditingTrait; 17 | public function getAuditors() 18 | { 19 | return [ 'DateInserted', 'DateUpdated', ]; 20 | } 21 | 22 | // definitions 23 | protected $table = 'GDN_Session'; 24 | protected $primaryKey = 'SessionID'; 25 | public $incrementing = false; 26 | 27 | public function getDates() 28 | { 29 | return [ 'DateInserted', 'DateUpdated', ]; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/models/UserRepository.php: -------------------------------------------------------------------------------- 1 | roles()->save($role); 27 | } 28 | \DB::commit(); 29 | 30 | return $user; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/views/themes/default/views/modules/drafts.php: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 | 17 |
-------------------------------------------------------------------------------- /src/views/themes/default/views/moderation/confirmcommentdeletes.php: -------------------------------------------------------------------------------- 1 | 2 |

Data('Title'); ?>

3 | Form->Open(); 5 | echo $this->Form->Errors(); 6 | 7 | $CountCheckedComments = GetValue('CountCheckedComments', $this->Data, 0); 8 | echo Wrap(sprintf( 9 | T('AboutToDelete', 'You are about to delete %s.'), 10 | Plural($CountCheckedComments, '%s comment', '%s comments') 11 | ), 'p'); 12 | 13 | echo '

'.T('Are you sure you wish to continue?').'

'; 14 | 15 | echo '
', 16 | $this->Form->Button('OK', array('class' => 'Button Primary')), 17 | $this->Form->Button('Cancel', array('type' => 'button', 'class' => 'Button Close')), 18 | '
'; 19 | 20 | echo $this->Form->Close(); 21 | -------------------------------------------------------------------------------- /src/views/themes/default/views/drafts/index.php: -------------------------------------------------------------------------------- 1 | '.$this->Data('Title').''; 3 | include($this->FetchViewLocation('helper_functions', 'discussions', 'vanilla')); 4 | $Session = Gdn::Session(); 5 | $ShowOptions = TRUE; 6 | $Alt = ''; 7 | $ViewLocation = $this->FetchViewLocation('drafts', 'drafts'); 8 | // WriteFilterTabs($this); 9 | echo Gdn_Theme::Module('DiscussionFilterModule'); 10 | if ($this->DraftData->NumRows() > 0) { 11 | echo $this->Pager->ToString('less'); 12 | ?> 13 | 18 | Pager->ToString('more'); 20 | } else { 21 | ?> 22 |
23 | integer('UserID'); 18 | $table->integer('RoleID')->index('IX_UserRole_RoleID'); 19 | $table->primary(['UserID','RoleID']); 20 | }); 21 | } 22 | 23 | 24 | /** 25 | * Reverse the migrations. 26 | * 27 | * @return void 28 | */ 29 | public function down() 30 | { 31 | Schema::drop('GDN_UserRole'); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/models/ActivityType.php: -------------------------------------------------------------------------------- 1 | 'required|max:20', 10 | 'AllowComments' => 'boolean', 11 | 'ShowIcon' => 'boolean', 12 | 'ProfileHeadline' => 'max:255', 13 | 'FullHeadline' => 'max:255', 14 | 'RouteCode' => 'max:255', 15 | 'Notify' => 'boolean', 16 | 'Public' => 'boolean', 17 | ]; 18 | 19 | // definitions 20 | protected $table = 'GDN_ActivityType'; 21 | protected $primaryKey = 'ActivityTypeID'; 22 | 23 | // relations 24 | public function activity() 25 | { 26 | return $this->belongsTo( 27 | '\BishopB\Forum\Activity', 'ActivityTypeID', 'ActivityTypeID' 28 | ); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/models/Ban.php: -------------------------------------------------------------------------------- 1 | 'required|in:IPAddress,Name,Email', 10 | 'BanValue' => 'required|max:50|unique_with:GDN_Ban,BanType', 11 | 'Notes' => 'max:255', 12 | 'CountUsers' => 'integer|min:0', 13 | 'CountBlockedRegistrations' => 'integer|min:0', 14 | ]; 15 | 16 | // auditing 17 | use AuditingTrait; 18 | public function getAuditors() 19 | { 20 | return [ 'InsertUserID', 'DateInserted', ]; 21 | } 22 | 23 | // definitions 24 | protected $table = 'GDN_Ban'; 25 | protected $primaryKey = 'BanID'; 26 | 27 | public function getDates() 28 | { 29 | return [ 'DateInserted', ]; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/migrations/2014_09_23_194713_create_GDN_Spammer_table.php: -------------------------------------------------------------------------------- 1 | integer('UserID')->primary(); 18 | $table->smallInteger('CountSpam')->unsigned()->default(0); 19 | $table->smallInteger('CountDeletedSpam')->unsigned()->default(0); 20 | }); 21 | } 22 | 23 | 24 | /** 25 | * Reverse the migrations. 26 | * 27 | * @return void 28 | */ 29 | public function down() 30 | { 31 | Schema::drop('GDN_Spammer'); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/migrations/2014_09_23_194713_create_GDN_AnalyticsLocal_table.php: -------------------------------------------------------------------------------- 1 | string('TimeSlot', 8)->unique('UX_AnalyticsLocal'); 18 | $table->integer('Views')->nullable(); 19 | $table->integer('EmbedViews')->nullable(); 20 | }); 21 | } 22 | 23 | 24 | /** 25 | * Reverse the migrations. 26 | * 27 | * @return void 28 | */ 29 | public function down() 30 | { 31 | Schema::drop('GDN_AnalyticsLocal'); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/migrations/2014_09_23_194713_create_GDN_UserMeta_table.php: -------------------------------------------------------------------------------- 1 | integer('UserID'); 18 | $table->string('Name')->index('IX_UserMeta_Name'); 19 | $table->text('Value')->nullable(); 20 | $table->primary(['UserID','Name']); 21 | }); 22 | } 23 | 24 | 25 | /** 26 | * Reverse the migrations. 27 | * 28 | * @return void 29 | */ 30 | public function down() 31 | { 32 | Schema::drop('GDN_UserMeta'); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/models/RoleRepository.php: -------------------------------------------------------------------------------- 1 | resolve(\Auth::user()); 20 | } catch (NoVanillaUserMappedToUser $ex) { 21 | if (\Auth::user()) { 22 | throw new NoVanillaUserMappedToAuthenticatedUser(); 23 | } else { 24 | throw new NoVanillaUserMappedToGuest(); 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/views/themes/default/views/post/editcomment.php: -------------------------------------------------------------------------------- 1 | 4 |
5 |
6 |
7 |
8 | Form->Open(); 10 | echo $this->Form->Errors(); 11 | echo $this->Form->BodyBox('Body', array('Table' => 'Comment', 'tabindex' => 1)); 12 | echo "
\n"; 13 | echo Anchor(T('Cancel'), '/', 'Button Cancel').' '; 14 | echo $this->Form->Button('Save Comment', array('class' => 'Button Primary CommentButton', 'tabindex' => 2)); 15 | echo "
\n"; 16 | echo $this->Form->Close(); 17 | ?> 18 |
19 |
20 |
21 |
-------------------------------------------------------------------------------- /src/services/UserMapperById.php: -------------------------------------------------------------------------------- 1 | getKey()); 22 | } 23 | 24 | if (null === $user) { 25 | throw new NoVanillaUserMappedToUser(); 26 | } 27 | 28 | return $user; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/views/themes/default/views/discussions/bookmarked.php: -------------------------------------------------------------------------------- 1 | Title(T('My Bookmarks')); 3 | include($this->FetchViewLocation('helper_functions', 'discussions', 'vanilla')); 4 | 5 | // WriteFilterTabs($this); 6 | if ($this->DiscussionData->NumRows() > 0 || (is_object($this->AnnounceData) && $this->AnnounceData->NumRows() > 0)) { 7 | ?> 8 | 11 | $this->Data('CountDiscussions'), 'CurrentRecords' => $this->Data('Discussions')->NumRows()); 13 | if ($this->Data('_PagerUrl')) { 14 | $PagerOptions['Url'] = $this->Data('_PagerUrl'); 15 | } 16 | echo PagerModule::Write($PagerOptions); 17 | } else { 18 | ?> 19 |
20 | string('Nonce', 200)->primary(); 18 | $table->string('Token', 128); 19 | $table->timestamp('Timestamp')->default(DB::raw('CURRENT_TIMESTAMP')); 20 | }); 21 | } 22 | 23 | 24 | /** 25 | * Reverse the migrations. 26 | * 27 | * @return void 28 | */ 29 | public function down() 30 | { 31 | Schema::drop('GDN_UserAuthenticationNonce'); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/services/UserMapperByClosure.php: -------------------------------------------------------------------------------- 1 | closure = $closure; 18 | } 19 | 20 | /** 21 | * @return BishopB\Forum\User 22 | * @throws BishopB\Forum\NoVanillaUserMappedToUser 23 | */ 24 | public function resolve(\Illuminate\Auth\UserInterface $user = null) 25 | { 26 | $user = call_user_func($this->closure, $user); 27 | if (! $user instanceof User) { 28 | throw new NoVanillaUserMappedToUser(); 29 | } 30 | 31 | return $user; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/views/themes/default/views/categories/table.php: -------------------------------------------------------------------------------- 1 | 2 |

Data('Title'); ?>

3 |
Description(); ?>
4 | FireEvent('AfterDescription'); 6 | $this->FireEvent('AfterPageTitle'); 7 | $Categories = CategoryModel::MakeTree($this->Data('Categories'), $this->Data('Category', NULL)); 8 | 9 | if (C('Vanilla.Categories.DoHeadings')) { 10 | foreach ($Categories as $Category) { 11 | ?> 12 |
13 |

14 | 17 |
18 | -------------------------------------------------------------------------------- /src/migrations/2014_09_23_194713_create_GDN_UserComment_table.php: -------------------------------------------------------------------------------- 1 | integer('UserID'); 18 | $table->integer('CommentID'); 19 | $table->float('Score', 10, 0)->nullable(); 20 | $table->dateTime('DateLastViewed')->nullable(); 21 | $table->primary(['UserID','CommentID']); 22 | }); 23 | } 24 | 25 | 26 | /** 27 | * Reverse the migrations. 28 | * 29 | * @return void 30 | */ 31 | public function down() 32 | { 33 | Schema::drop('GDN_UserComment'); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/models/Comment.php: -------------------------------------------------------------------------------- 1 | 'required|exists:GDN_Discussion,DiscussionID', 10 | // 'Body' => none, 11 | 'Format' => 'max:20', 12 | 'Flag' => 'boolean', 13 | 'Score' => 'numeric', 14 | // 'Attributes' => none, 15 | ]; 16 | 17 | // auditing 18 | use AuditingTrait; 19 | 20 | // definitions 21 | protected $table = 'GDN_Comment'; 22 | protected $primaryKey = 'CommentID'; 23 | 24 | public function getDates() 25 | { 26 | return [ 'DateInserted', 'DateUpdated', 'DateDeleted' ]; 27 | } 28 | 29 | // relations 30 | public function discussion() 31 | { 32 | return $this->belongsTo( 33 | '\BishopB\Forum\Discussion', 'DiscussionID', 'DiscussionID' 34 | ); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/migrations/2014_09_23_194713_create_GDN_UserCategory_table.php: -------------------------------------------------------------------------------- 1 | integer('UserID'); 18 | $table->integer('CategoryID'); 19 | $table->dateTime('DateMarkedRead')->nullable(); 20 | $table->boolean('Unfollow')->default(0); 21 | $table->primary(['UserID','CategoryID']); 22 | }); 23 | } 24 | 25 | 26 | /** 27 | * Reverse the migrations. 28 | * 29 | * @return void 30 | */ 31 | public function down() 32 | { 33 | Schema::drop('GDN_UserCategory'); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/migrations/2014_09_23_194713_create_GDN_UserAuthentication_table.php: -------------------------------------------------------------------------------- 1 | string('ForeignUserKey'); 18 | $table->string('ProviderKey', 64); 19 | $table->integer('UserID')->index('FK_UserAuthentication_UserID'); 20 | $table->primary(['ForeignUserKey','ProviderKey']); 21 | }); 22 | } 23 | 24 | 25 | /** 26 | * Reverse the migrations. 27 | * 28 | * @return void 29 | */ 30 | public function down() 31 | { 32 | Schema::drop('GDN_UserAuthentication'); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/views/themes/default/views/modules/categoryfollowtoggle.php: -------------------------------------------------------------------------------- 1 | GetPreference('ShowAllCategories'); 3 | $Url = Gdn::Request()->Path(); 4 | ?> 5 | 6 |
7 |
8 |
9 | 10 | 'CurrentFilter')); 13 | echo ' | '; 14 | echo Wrap(Anchor(T('followed categories'), $Url.'?ShowAllCategories=false'), 'span'); 15 | else: 16 | echo Wrap(Anchor(T('all categories'), $Url.'?ShowAllCategories=true'), 'span'); 17 | echo ' | '; 18 | echo Wrap(T('followed categories'), 'span', array('class' => 'CurrentFilter')); 19 | endif; 20 | ?> 21 |
22 |
-------------------------------------------------------------------------------- /src/models/ActivityComment.php: -------------------------------------------------------------------------------- 1 | 'required|exists:GDN_Activity,ActivityID', 10 | 'Body' => 'required', 11 | 'Format' => 'required|max:20', 12 | ]; 13 | 14 | // auditing 15 | use AuditingTrait; 16 | public function getAuditors() 17 | { 18 | return [ 'InsertUserID', 'DateInserted', 'InsertIPAddress', ]; 19 | } 20 | 21 | // defintions 22 | protected $table = 'GDN_ActivityComment'; 23 | protected $primaryKey = 'ActivityCommentID'; 24 | 25 | public function getDates() 26 | { 27 | return [ 'DateInserted', ]; 28 | } 29 | 30 | // relations 31 | public function activity() 32 | { 33 | return $this->belongsTo( 34 | '\BishopB\Forum\Activity', 'ActivityID', 'ActivityID' 35 | ); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/models/Regarding.php: -------------------------------------------------------------------------------- 1 | 'required|max:255', 10 | 'ForeignType' => 'required|max:32', 11 | 'ForeignID' => 'required|integer', 12 | // 'OriginalContent' => none, 13 | 'ParentType' => 'max:32', 14 | 'ParentID' => 'integer', 15 | 'ForeignURL' => 'url|max:255', 16 | // 'Comment' => none, 17 | 'Reports' => 'integer', 18 | ]; 19 | 20 | // auditing 21 | use AuditingTrait; 22 | public function getAuditors() 23 | { 24 | return [ 'InsertUserID', 'DateInserted', ]; 25 | } 26 | 27 | // definitions 28 | protected $table = 'GDN_Regarding'; 29 | protected $primaryKey = 'RegardingID'; 30 | 31 | public function getDates() 32 | { 33 | return [ 'DateInserted', ]; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/migrations/2014_09_23_194713_create_GDN_Session_table.php: -------------------------------------------------------------------------------- 1 | char('SessionID', 32)->primary(); 18 | $table->integer('UserID')->default(0); 19 | $table->dateTime('DateInserted'); 20 | $table->dateTime('DateUpdated'); 21 | $table->string('TransientKey', 12); 22 | $table->text('Attributes')->nullable(); 23 | }); 24 | } 25 | 26 | 27 | /** 28 | * Reverse the migrations. 29 | * 30 | * @return void 31 | */ 32 | public function down() 33 | { 34 | Schema::drop('GDN_Session'); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/migrations/2014_09_23_194713_create_GDN_TagDiscussion_table.php: -------------------------------------------------------------------------------- 1 | integer('TagID'); 18 | $table->integer('DiscussionID'); 19 | $table->integer('CategoryID')->index('IX_TagDiscussion_CategoryID'); 20 | $table->dateTime('DateInserted')->nullable(); 21 | $table->primary(['TagID','DiscussionID']); 22 | }); 23 | } 24 | 25 | 26 | /** 27 | * Reverse the migrations. 28 | * 29 | * @return void 30 | */ 31 | public function down() 32 | { 33 | Schema::drop('GDN_TagDiscussion'); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/migrations/2014_09_23_194713_create_GDN_UserMergeItem_table.php: -------------------------------------------------------------------------------- 1 | integer('MergeID')->index('FK_UserMergeItem_MergeID'); 18 | $table->string('Table', 30); 19 | $table->string('Column', 30); 20 | $table->integer('RecordID'); 21 | $table->integer('OldUserID'); 22 | $table->integer('NewUserID'); 23 | }); 24 | } 25 | 26 | 27 | /** 28 | * Reverse the migrations. 29 | * 30 | * @return void 31 | */ 32 | public function down() 33 | { 34 | Schema::drop('GDN_UserMergeItem'); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/views/themes/default/views/discussion/announce.php: -------------------------------------------------------------------------------- 1 | 2 | 3 |

Data('Title'); ?>

4 | 5 | Form->Open(); 7 | echo $this->Form->Errors(); 8 | 9 | echo '
'.T('Where do you want to announce this discussion?').'
'; 10 | 11 | echo '
', $this->Form->Radio('Announce', '@'.sprintf(T('In %s.'), $this->Data('Category.Name')), array('Value' => '2')), '
'; 12 | echo '
', $this->Form->Radio('Announce', '@'.sprintf(T('In %s and recent discussions.'), $this->Data('Category.Name')), array('Value' => '1')), '
'; 13 | echo '
', $this->Form->Radio('Announce', '@'.T("Don't announce."), array('Value' => '0')), '
'; 14 | 15 | echo '
'; 16 | echo $this->Form->Button('OK'); 17 | echo $this->Form->Button('Cancel', array('type' => 'button', 'class' => 'Button Close')); 18 | echo '
'; 19 | echo $this->Form->Close(); 20 | ?> 21 | -------------------------------------------------------------------------------- /src/models/ConversationMessage.php: -------------------------------------------------------------------------------- 1 | 'required|exists:GDN_Conversation,ConversationID', 9 | // 'Body' => none, 10 | 'Format' => 'max:20', 11 | ]; 12 | 13 | // auditing 14 | use AuditingTrait; 15 | public function getAuditors() 16 | { 17 | return [ 18 | 'InsertUserID', 'DateInserted', 'InsertIPAddress', 19 | ]; 20 | } 21 | 22 | // definitions 23 | protected $table = 'GDN_ConversationMessage'; 24 | protected $primaryKey = 'MessageID'; 25 | 26 | public function getDates() 27 | { 28 | return [ 'DateInserted', ]; 29 | } 30 | 31 | // relations 32 | public function conversation() 33 | { 34 | return $this->belongsTo( 35 | '\BishopB\Forum\Conversation', 'ConversationID', 'ConversationID' 36 | ); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bishopb/laravel-forums", 3 | "description": "Forums and discussion boards for Laravel, using the Vanilla Forums engine.", 4 | "license": "GPL-2.0", 5 | "authors": [ 6 | { 7 | "name": "Bishop Bettini", "email": "bishop@php.net" 8 | } 9 | ], 10 | "require": { 11 | "bishopb/vanilla": "2.2.3.6-patch1", 12 | "laravel/framework": "~4.2", 13 | "watson/validating": "0.10.*", 14 | "felixkiss/uniquewith-validator": "1.1.*" 15 | }, 16 | "autoload": { 17 | "classmap": [ "src" ], 18 | "psr-4": { 19 | "BishopB\\Forum\\": "src/" 20 | } 21 | }, 22 | "config": { 23 | "preferred-install": "dist" 24 | }, 25 | "minimum-stability": "stable", 26 | "require-dev": { 27 | "mockery/mockery": "~0.9", 28 | "phpunit/phpunit": "~4.0" 29 | }, 30 | "autoload-dev": { 31 | "psr-4": { 32 | "BishopB\\ForumTest\\": "tests/" 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/models/Invitation.php: -------------------------------------------------------------------------------- 1 | 'required|email|max:200', 10 | 'Name' => 'max:50', 11 | // 'RoleIDs' => none, 12 | 'Code' => 'max:50', 13 | 'AcceptedUserID' => 'exists:GDN_User,UserID', 14 | 'DateExpires' => 'date', 15 | ]; 16 | 17 | // auditing 18 | use AuditingTrait; 19 | public function getAuditors() 20 | { 21 | return [ 'InsertUserID', 'DateInserted', ]; 22 | } 23 | 24 | // definitions 25 | protected $table = 'GDN_Invitation'; 26 | protected $primaryKey = 'InvitationID'; 27 | 28 | public function getDates() 29 | { 30 | return [ 'DateInserted', 'DateExpires', ]; 31 | } 32 | 33 | // relations 34 | public function accepting_user() 35 | { 36 | return $this->hasOne('\BishopB\Forum\User', 'UserID', 'AcceptedUserID'); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/models/Media.php: -------------------------------------------------------------------------------- 1 | 'required|max:255', 10 | 'Path' => 'required|max:255', 11 | 'Type' => 'required|max:128', 12 | 'Size' => 'integer', 13 | 'ForeignID' => 'integer', 14 | 'ForeginTable' => 'max:24', 15 | 'ImageWidth' => 'integer|min:0', 16 | 'ImageHeight' => 'integer|min:0', 17 | 'ThumbWidth' => 'integer|min:0', 18 | 'ThumbHeight' => 'integer|min:0', 19 | 'ThumbPath' => 'max:255', 20 | ]; 21 | 22 | // auditing 23 | use AuditingTrait; 24 | public function getAuditors() 25 | { 26 | return [ 'InsertUserID', 'DateInserted', ]; 27 | } 28 | 29 | // definitions 30 | protected $table = 'GDN_Media'; 31 | protected $primaryKey = 'MediaID'; 32 | 33 | public function getDates() 34 | { 35 | return [ 'DateInserted', ]; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/migrations/2014_09_23_194713_create_GDN_Role_table.php: -------------------------------------------------------------------------------- 1 | integer('RoleID', true); 18 | $table->string('Name', 100); 19 | $table->string('Description', 500)->nullable(); 20 | $table->integer('Sort')->nullable(); 21 | $table->boolean('Deletable')->default(1); 22 | $table->boolean('CanSession')->default(1); 23 | $table->boolean('PersonalInfo')->default(0); 24 | }); 25 | } 26 | 27 | 28 | /** 29 | * Reverse the migrations. 30 | * 31 | * @return void 32 | */ 33 | public function down() 34 | { 35 | Schema::drop('GDN_Role'); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/services/VanillaHelperTrait.php: -------------------------------------------------------------------------------- 1 | Set($key, $value, true /*overwrite*/, true /*persist*/); 24 | } 25 | 26 | /** 27 | * Get a value from the Vanilla run-time configuration 28 | */ 29 | public static function get($key) 30 | { 31 | return \Gdn::Config()->Get($key); 32 | } 33 | 34 | /** 35 | * Get the version of Vanilla installed. 36 | * TODO Pull from Vanilla's index.php 37 | */ 38 | public static function get_vanilla_version() 39 | { 40 | return '2.2.16.1'; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/views/themes/default/views/discussion/profilecomments.php: -------------------------------------------------------------------------------- 1 | Data('Comments') as $Comment) { 3 | $Permalink = '/discussion/comment/'.$Comment->CommentID.'/#Comment_'.$Comment->CommentID; 4 | $User = UserBuilder($Comment, 'Insert'); 5 | $this->EventArguments['User'] = $User; 6 | ?> 7 |
  • 8 | FireEvent('BeforeItemContent'); ?> 9 |
    10 |
    Body, $Comment->Format), FALSE), 250); 12 | ?>
    13 |
    14 | DiscussionName), $Permalink); ?> 15 | 16 | DateInserted), $Permalink); ?> 17 |
    18 |
    19 |
  • 20 | FetchViewLocation('helper_functions'); 3 | 4 | ?> 5 |
    6 | 7 |
    8 | Data('Content'); 10 | $ContentItems = sizeof($Content); 11 | 12 | if ($Content): 13 | 14 | if ($this->Group): 15 | $Content = array_chunk($Content, $this->Group); 16 | endif; 17 | 18 | foreach ($Content as $ContentChunk): 19 | if ($this->Group): 20 | echo '
    '; 21 | foreach ($ContentChunk as $ContentItem): 22 | WritePromotedContent($ContentItem, $this); 23 | endforeach; 24 | echo '
    '; 25 | else: 26 | WritePromotedContent($ContentChunk, $this); 27 | endif; 28 | endforeach; 29 | 30 | endif; 31 | ?> 32 |
    33 |
    -------------------------------------------------------------------------------- /src/views/themes/default/views/post/index.php: -------------------------------------------------------------------------------- 1 | Data('Forms'); 4 | // Loop through the form collection and write out the handles 5 | $FormToggleMenu = new ToggleMenuModule(); 6 | foreach ($Forms as $Form) { 7 | $Code = GetValue('Name', $Form); 8 | $Active = strtolower($Code) == strtolower($this->Data('CurrentFormName')); 9 | if ($Active) 10 | $FormToggleMenu->CurrentLabelCode($Code); 11 | 12 | $FormToggleMenu->AddLabel(GetValue('Label', $Form), $Code); 13 | } 14 | echo $FormToggleMenu->ToString(); 15 | 16 | // Now loop through the form collection and dump the forms 17 | foreach ($Forms as $Form) { 18 | $Name = GetValue('Name', $Form); 19 | $Active = strtolower($Name) == strtolower($this->Data('CurrentFormName')); 20 | $Url = GetValue('Url', $Form); 21 | echo '
    '; 22 | // echo ProxyRequest(Url($Url.'?DeliveryType=VIEW', TRUE)); 23 | echo '
    '; 24 | echo '
    '; 25 | } 26 | -------------------------------------------------------------------------------- /src/models/Message.php: -------------------------------------------------------------------------------- 1 | 'required', 10 | 'Format' => 'max:20', 11 | 'AllowDismiss' => 'boolean', 12 | 'Enabled' => 'boolean', 13 | 'Application' => 'max:255', 14 | 'Controller' => 'max:255', 15 | 'Method' => 'max:255', 16 | 'Category' => 'exists:GDN_Category,CategoryID', 17 | 'IncludeSubcategories' => 'boolean', 18 | 'AssetTarget' => 'max:20', 19 | 'CssClass' => 'max:20', 20 | 'Sort' => 'integer', 21 | ]; 22 | 23 | // definitions 24 | protected $table = 'GDN_Message'; 25 | protected $primaryKey = 'MessageID'; 26 | 27 | // relations 28 | public function category() 29 | { 30 | return $this->hasOne( 31 | '\BishopB\Forum\Category', 'CategoryID', 'CategoryID' 32 | ); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/migrations/2014_09_23_194713_create_GDN_ActivityComment_table.php: -------------------------------------------------------------------------------- 1 | integer('ActivityCommentID', true); 18 | $table->integer('ActivityID')->index('FK_ActivityComment_ActivityID'); 19 | $table->text('Body'); 20 | $table->string('Format', 20); 21 | $table->integer('InsertUserID'); 22 | $table->dateTime('DateInserted'); 23 | $table->string('InsertIPAddress', 15)->nullable(); 24 | }); 25 | } 26 | 27 | 28 | /** 29 | * Reverse the migrations. 30 | * 31 | * @return void 32 | */ 33 | public function down() 34 | { 35 | Schema::drop('GDN_ActivityComment'); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/services/UserMapperInterface.php: -------------------------------------------------------------------------------- 1 | enum('SlotType', array('d','w','m','y','a')); 18 | $table->dateTime('TimeSlot'); 19 | $table->string('Source', 10)->default('Total'); 20 | $table->integer('CategoryID')->default(0); 21 | $table->integer('UserID'); 22 | $table->integer('Points')->default(0); 23 | $table->primary(['SlotType','TimeSlot','Source','CategoryID','UserID'], 'composite'); 24 | }); 25 | } 26 | 27 | 28 | /** 29 | * Reverse the migrations. 30 | * 31 | * @return void 32 | */ 33 | public function down() 34 | { 35 | Schema::drop('GDN_UserPoints'); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/views/themes/default/README.md: -------------------------------------------------------------------------------- 1 | This is a direct copy of the default theme from Vanilla into a spot appropriate for Laravel. 2 | 3 | To change the theme, follow these modified Vanilla instructions: 4 | 5 | Part 1: CSS / Design 6 | ==================== 7 | If you like the layout and want to change only the look and feel of the forums, you can add your custom styles to `design/custom.css`. 8 | 9 | If you want to edit the look & feel of the administrative screens, also edit `design/customadmin.css`. 10 | 11 | If you want to affect non-forum pages, then you will have to edit the Vanilla source code itself. 12 | 13 | Part 2: HTML / Views (Advanced) 14 | =============================== 15 | If you want to adjust the layout as well, you need to edit the layout files. 16 | 17 | To add a banner or menu, change the footer, or any other major layout component, edit the `views/default.master.tpl` file. 18 | 19 | To change something specific about a particular part of Vanilla, find the file in `views/*` holding the existing content and change it there. 20 | 21 | [Additional help](http://vanillaforums.org/docs/themequickstart) may be found online. 22 | -------------------------------------------------------------------------------- /src/views/themes/default/views/discussions/index_rss.php: -------------------------------------------------------------------------------- 1 | 2 | Head->Title()); ?> 3 | 4 | 5 | DiscussionData->Result() as $Discussion) { 7 | ?> 8 | 9 | <?php echo Gdn_Format::Text($Discussion->Name); ?> 10 | Url; ?> 11 | DateInserted)); ?> 12 | Category); ?> 13 | FirstName); ?> 14 | DiscussionID . '@' . Url('/discussions'); ?> 15 | Body, $Discussion->Format); ?>]]> 16 | 17 | integer('MergeID', true); 18 | $table->integer('OldUserID')->index('FK_UserMerge_OldUserID'); 19 | $table->integer('NewUserID')->index('FK_UserMerge_NewUserID'); 20 | $table->dateTime('DateInserted'); 21 | $table->integer('InsertUserID'); 22 | $table->dateTime('DateUpdated')->nullable(); 23 | $table->integer('UpdateUserID')->nullable(); 24 | $table->text('Attributes')->nullable(); 25 | }); 26 | } 27 | 28 | 29 | /** 30 | * Reverse the migrations. 31 | * 32 | * @return void 33 | */ 34 | public function down() 35 | { 36 | Schema::drop('GDN_UserMerge'); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/migrations/2014_09_23_194713_create_GDN_ConversationMessage_table.php: -------------------------------------------------------------------------------- 1 | integer('MessageID', true); 18 | $table->integer('ConversationID')->index('FK_ConversationMessage_ConversationID'); 19 | $table->text('Body'); 20 | $table->string('Format', 20)->nullable(); 21 | $table->integer('InsertUserID')->nullable()->index('FK_ConversationMessage_InsertUserID'); 22 | $table->dateTime('DateInserted'); 23 | $table->string('InsertIPAddress', 15)->nullable(); 24 | }); 25 | } 26 | 27 | 28 | /** 29 | * Reverse the migrations. 30 | * 31 | * @return void 32 | */ 33 | public function down() 34 | { 35 | Schema::drop('GDN_ConversationMessage'); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/services/GardenPluginManager.php: -------------------------------------------------------------------------------- 1 | $Sender, 20 | 'EventClassName' => $EventClassName, 21 | 'EventName' => $EventName, 22 | 'EventHandlerType' => $EventHandlerType, 23 | 'Options' => $Options, 24 | ]); 25 | 26 | // log if we want to 27 | if (\Config::get('forum::package.trace-include-events', false)) { 28 | Trace(['EventClassName' => $EventClassName, 'EventName' => $EventName]); 29 | } 30 | 31 | // defer 32 | return parent::CallEventHandlers( 33 | $Sender, $EventClassName, $EventName, $EventHandlerType, $Options 34 | ); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/migrations/2014_09_23_194713_create_GDN_Ban_table.php: -------------------------------------------------------------------------------- 1 | integer('BanID', true); 18 | $table->enum('BanType', array('IPAddress','Name','Email')); 19 | $table->string('BanValue', 50); 20 | $table->string('Notes', 255)->nullable(); 21 | $table->integer('CountUsers')->unsigned()->default(0); 22 | $table->integer('CountBlockedRegistrations')->unsigned()->default(0); 23 | $table->integer('InsertUserID'); 24 | $table->dateTime('DateInserted'); 25 | $table->unique(['BanType','BanValue'], 'UX_Ban'); 26 | }); 27 | } 28 | 29 | 30 | /** 31 | * Reverse the migrations. 32 | * 33 | * @return void 34 | */ 35 | public function down() 36 | { 37 | Schema::drop('GDN_Ban'); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/controllers/PassthruController.php: -------------------------------------------------------------------------------- 1 | request = $request; 18 | $this->mapper = $mapper; 19 | } 20 | 21 | public function index() 22 | { 23 | // get the segments after our route prefix (/foo/bar) and feed into vanilla 24 | $segments = $this->request->segments(); 25 | if (forum_get_route_prefix() === head($segments)) { 26 | array_shift($segments); 27 | } 28 | 29 | // use a default if needed 30 | if (0 === count($segments)) { 31 | $segments = [ 'discussions' ]; 32 | } 33 | 34 | // run vanilla with the path and user we want 35 | $runner = new VanillaRunner(); 36 | $runner->login($this->mapper->current()); 37 | return $runner->view($segments); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/views/themes/default/views/modules/bookmarked.php: -------------------------------------------------------------------------------- 1 | FetchViewLocation('helper_functions'); 3 | require_once Gdn::Controller()->FetchViewLocation('helper_functions', 'Discussions', 'Vanilla'); 4 | 5 | $Bookmarks = $this->Data('Bookmarks'); 6 | ?> 7 |
    8 |

    9 | Result()) > 0): ?> 10 | 11 |
      12 | Result() as $Discussion) { 14 | WriteModuleDiscussion($Discussion); 15 | } 16 | if ($Bookmarks->NumRows() == $this->Limit) { 17 | ?> 18 |
    • 19 | 20 |
    21 | 22 | 23 |
    24 | '); 28 | ?> 29 |
    30 | 31 |
    -------------------------------------------------------------------------------- /src/migrations/2014_09_23_194713_create_GDN_ActivityType_table.php: -------------------------------------------------------------------------------- 1 | integer('ActivityTypeID', true); 18 | $table->string('Name', 20); 19 | $table->boolean('AllowComments')->default(0); 20 | $table->boolean('ShowIcon')->default(0); 21 | $table->string('ProfileHeadline', 255)->nullable(); 22 | $table->string('FullHeadline', 255)->nullable(); 23 | $table->string('RouteCode', 255)->nullable(); 24 | $table->boolean('Notify')->default(0); 25 | $table->boolean('Public')->default(1); 26 | }); 27 | } 28 | 29 | 30 | /** 31 | * Reverse the migrations. 32 | * 33 | * @return void 34 | */ 35 | public function down() 36 | { 37 | Schema::drop('GDN_ActivityType'); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/views/themes/default/views/discussions/unread.php: -------------------------------------------------------------------------------- 1 | FetchViewLocation('helper_functions', 'discussions', 'vanilla'); 4 | 5 | echo '

    '. 6 | AdminCheck(NULL, array('', ' ')). 7 | $this->Data('Title'). 8 | '

    '; 9 | 10 | if ($Description = $this->Description()) { 11 | echo Wrap($Description, 'div', array('class' => 'P PageDescription')); 12 | } 13 | // echo Gdn_Theme::Module('DiscussionFilterModule'); 14 | 15 | if ($this->DiscussionData->NumRows() > 0 || (isset($this->AnnounceData) && is_object($this->AnnounceData) && $this->AnnounceData->NumRows() > 0)) { 16 | ?> 17 |
      18 | FetchViewLocation('discussions')); ?> 19 |
    20 | $this->Data('CountDiscussions'), 'CurrentRecords' => $this->Data('Discussions')->NumRows()); 22 | if ($this->Data('_PagerUrl')) 23 | $PagerOptions['Url'] = $this->Data('_PagerUrl'); 24 | 25 | PagerModule::Write($PagerOptions); 26 | } else { 27 | ?> 28 |
    29 | false, 16 | 17 | /** 18 | * The logging level used to record trace. If `trace` is false, this 19 | * has no effect. If `trace` is true, the level given is used. Possible 20 | * levels are: debug, info, notice, warning, error, critical, and alert 21 | */ 22 | 'trace-level' => 'debug', 23 | 24 | /** 25 | * If you would like to see the events that Vanilla's firing, enable 26 | * `trace-include-events`. This has no effect unless `trace` is on. 27 | */ 28 | 'trace-include-events' => false, 29 | 30 | /** 31 | * If you would like to see the database queries that Vanilla's making, enable 32 | * `trace-include-queries`. This has no effect unless `trace` is on. 33 | */ 34 | 'trace-include-queries' => false, 35 | ]; 36 | -------------------------------------------------------------------------------- /src/models/Attachment.php: -------------------------------------------------------------------------------- 1 | 'required|max:64', 10 | 'ForeignID' => 'required|max:50', 11 | 'ForeignUserID' => 'required|exists:GDN_User,UserID', 12 | 'Source' => 'required|max:64', 13 | 'SourceID' => 'required|max:32', 14 | 'SourceURL' => 'required|url|max:255', 15 | // 'Attributes' => none, 16 | ]; 17 | 18 | // auditing 19 | use AuditingTrait; 20 | public function getAuditors() 21 | { 22 | return [ 23 | 'InsertUserID', 'DateInserted', 'InsertIPAddress', 24 | 'UpdateUserID', 'DateUpdated', 'UpdateIPAddress', 25 | ]; 26 | } 27 | 28 | // definitions 29 | protected $table = 'GDN_Attachment'; 30 | protected $primaryKey = 'AttachmentID'; 31 | 32 | public function getDates() 33 | { 34 | return [ 'DateInserted', 'DateUpdated', ]; 35 | } 36 | 37 | // relations 38 | public function user() 39 | { 40 | return $this->hasOne('\BishopB\Forum\User', 'UserID', 'ForeignUserID'); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/models/Permission.php: -------------------------------------------------------------------------------- 1 | 'exists:GDN_Role,RoleID', 10 | 'JunctionTable' => 'max:100', 11 | 'JunctionColumn' => 'max:100', 12 | 'JunctionID' => 'integer', 13 | // any other columns with dots in them are boolean 14 | ]; 15 | 16 | // definitions 17 | protected $table = 'GDN_Permission'; 18 | protected $primaryKey = 'PermissionID'; 19 | 20 | // relations 21 | public function role() 22 | { 23 | return $this->hasOne( 24 | '\BishopB\Forum\Role', 'RoleID', 'RoleID' 25 | ); 26 | } 27 | 28 | // custom 29 | /** 30 | * Any permission attribute we set needs to be boolean. 31 | * Since Vanilla can add these columns at run time, we have to react at 32 | * run-time. 33 | */ 34 | public function setAttribute($key, $value) 35 | { 36 | if (str_contains($key, '.') && ! array_key_exists($key, $this->rules)) { 37 | $this->getValidator()->addRule($key, 'boolean'); 38 | } 39 | 40 | return parent::setAttribute($key, $value); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/models/Tag.php: -------------------------------------------------------------------------------- 1 | 'required|max:255', 10 | 'FullName' => 'required|max:255', 11 | 'Type' => 'max:20', 12 | 'ParentTagID' => 'exists:GDN_Tag,TagID', 13 | 'CategoryID' => 'exists:GDN_Category,CategoryID|unique_with:GDN_Tag,Name', 14 | 'CountDiscussions' => 'integer|min:0', 15 | ]; 16 | 17 | // auditing 18 | use AuditingTrait; 19 | public function getAuditors() 20 | { 21 | return [ 'InsertUserID', 'DateInserted', ]; 22 | } 23 | 24 | // definitions 25 | protected $table = 'GDN_Tag'; 26 | protected $primaryKey = 'TagID'; 27 | 28 | public function getDates() 29 | { 30 | return [ 'DateInserted', ]; 31 | } 32 | 33 | // relationships 34 | public function parent_tag() 35 | { 36 | return $this->hasOne('\BishopB\Forum\Tag', 'TagID', 'ParentTagID'); 37 | } 38 | 39 | public function category() 40 | { 41 | return $this->hasOne( 42 | '\BishopB\Forum\Category', 'CategoryID', 'CategoryID' 43 | ); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/migrations/2014_09_23_194713_create_GDN_UserAuthenticationToken_table.php: -------------------------------------------------------------------------------- 1 | string('Token', 128); 18 | $table->string('ProviderKey', 64); 19 | $table->string('ForeignUserKey')->nullable(); 20 | $table->string('TokenSecret', 64); 21 | $table->enum('TokenType', array('request','access')); 22 | $table->boolean('Authorized'); 23 | $table->timestamp('Timestamp')->default(DB::raw('CURRENT_TIMESTAMP')); 24 | $table->integer('Lifetime'); 25 | $table->primary(['Token','ProviderKey']); 26 | }); 27 | } 28 | 29 | 30 | /** 31 | * Reverse the migrations. 32 | * 33 | * @return void 34 | */ 35 | public function down() 36 | { 37 | Schema::drop('GDN_UserAuthenticationToken'); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/migrations/2014_09_23_194713_create_GDN_UserDiscussion_table.php: -------------------------------------------------------------------------------- 1 | integer('UserID'); 18 | $table->integer('DiscussionID')->index('FK_UserDiscussion_DiscussionID'); 19 | $table->float('Score', 10, 0)->nullable(); 20 | $table->integer('CountComments')->default(0); 21 | $table->dateTime('DateLastViewed')->nullable(); 22 | $table->boolean('Dismissed')->default(0); 23 | $table->boolean('Bookmarked')->default(0); 24 | $table->boolean('Participated')->default(0); 25 | $table->primary(['UserID','DiscussionID']); 26 | }); 27 | } 28 | 29 | 30 | /** 31 | * Reverse the migrations. 32 | * 33 | * @return void 34 | */ 35 | public function down() 36 | { 37 | Schema::drop('GDN_UserDiscussion'); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/models/TagDiscussion.php: -------------------------------------------------------------------------------- 1 | 'required|integer', 10 | 'DiscussionID' => 'required|integer|unique_with:GDN_TagDiscussion,TagID', 11 | 'CategoryID' => 'required|exists:GDN_Category,CategoryID', 12 | ]; 13 | 14 | // auditing 15 | use AuditingTrait; 16 | public function getAuditors() 17 | { 18 | return [ 'DateInserted', ]; 19 | } 20 | 21 | // definitions 22 | protected $table = 'GDN_TagDiscussion'; 23 | use NoPrimaryKeyTrait; 24 | 25 | public function getDates() 26 | { 27 | return [ 'DateInserted', ]; 28 | } 29 | 30 | // relationships 31 | public function tag() 32 | { 33 | return $this->hasOne('\BishopB\Forum\Tag', 'TagID', 'TagID'); 34 | } 35 | 36 | public function discussion() 37 | { 38 | return $this->hasOne( 39 | '\BishopB\Forum\Discussion', 'DiscussionID', 'DiscussionID' 40 | ); 41 | } 42 | 43 | public function category() 44 | { 45 | return $this->hasOne( 46 | '\BishopB\Forum\Category', 'CategoryID', 'CategoryID' 47 | ); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/migrations/2014_09_23_194713_create_GDN_Invitation_table.php: -------------------------------------------------------------------------------- 1 | integer('InvitationID', true); 18 | $table->string('Email', 200)->index('IX_Invitation_Email'); 19 | $table->string('Name', 50)->nullable(); 20 | $table->text('RoleIDs')->nullable(); 21 | $table->string('Code', 50)->unique('UX_Invitation'); 22 | $table->integer('InsertUserID')->nullable(); 23 | $table->dateTime('DateInserted'); 24 | $table->integer('AcceptedUserID')->nullable(); 25 | $table->dateTime('DateExpires')->nullable(); 26 | $table->index(['InsertUserID','DateInserted'], 'IX_Invitation_userdate'); 27 | }); 28 | } 29 | 30 | 31 | /** 32 | * Reverse the migrations. 33 | * 34 | * @return void 35 | */ 36 | public function down() 37 | { 38 | Schema::drop('GDN_Invitation'); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/migrations/2014_09_23_194713_create_GDN_Tag_table.php: -------------------------------------------------------------------------------- 1 | integer('TagID', true); 18 | $table->string('Name', 255); 19 | $table->string('FullName', 255)->index('IX_Tag_FullName'); 20 | $table->string('Type', 20)->default('')->index('IX_Tag_Type'); 21 | $table->integer('ParentTagID')->nullable()->index('FK_Tag_ParentTagID'); 22 | $table->integer('InsertUserID')->nullable()->index('FK_Tag_InsertUserID'); 23 | $table->dateTime('DateInserted'); 24 | $table->integer('CategoryID')->default(-1); 25 | $table->integer('CountDiscussions')->default(0); 26 | $table->unique(['Name','CategoryID'], 'UX_Tag'); 27 | }); 28 | } 29 | 30 | 31 | /** 32 | * Reverse the migrations. 33 | * 34 | * @return void 35 | */ 36 | public function down() 37 | { 38 | Schema::drop('GDN_Tag'); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/models/BaseModel.php: -------------------------------------------------------------------------------- 1 | getTraits())) { 36 | $this->guarded = $this->guarded + $this->getAuditors(); 37 | } 38 | 39 | parent::__construct($attributes); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/services/UrlGenerator.php: -------------------------------------------------------------------------------- 1 | /library/core/functions.general.php 10 | * 2. /src/Illuminate/Support/helpers.php 11 | */ 12 | class UrlGenerator extends \Illuminate\Routing\UrlGenerator 13 | { 14 | public function to($path, $parameters = null, $secure = false) 15 | { 16 | return parent::to( 17 | $this->rewrite_url($path), 18 | (is_array($parameters) ? $parameters : []), 19 | $secure 20 | ); 21 | } 22 | 23 | public function asset($path, $secure = null) 24 | { 25 | return parent::to($this->rewrite_url($path), [], false); 26 | } 27 | 28 | private function rewrite_url($path) 29 | { 30 | if (starts_with($path, 'http') || starts_with($path, '//')) { // absolute 31 | return $path; 32 | 33 | } else if (starts_with($path, '{')) { // smarty template variable 34 | return $path; 35 | 36 | } else if (empty($path)) { // self 37 | return \Request::url(); 38 | 39 | } else { // relative 40 | return forum_get_route_prefix() . '/' . ltrim($path, '/'); 41 | } 42 | } 43 | } 44 | 45 | -------------------------------------------------------------------------------- /src/migrations/2014_09_23_194713_create_GDN_Regarding_table.php: -------------------------------------------------------------------------------- 1 | integer('RegardingID', true); 18 | $table->string('Type', 255)->index('FK_Regarding_Type'); 19 | $table->integer('InsertUserID'); 20 | $table->dateTime('DateInserted'); 21 | $table->string('ForeignType', 32); 22 | $table->integer('ForeignID'); 23 | $table->text('OriginalContent')->nullable(); 24 | $table->string('ParentType', 32)->nullable(); 25 | $table->integer('ParentID')->nullable(); 26 | $table->string('ForeignURL', 255)->nullable(); 27 | $table->text('Comment'); 28 | $table->integer('Reports')->nullable(); 29 | }); 30 | } 31 | 32 | 33 | /** 34 | * Reverse the migrations. 35 | * 36 | * @return void 37 | */ 38 | public function down() 39 | { 40 | Schema::drop('GDN_Regarding'); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/views/themes/default/views/drafts/drafts.php: -------------------------------------------------------------------------------- 1 | DraftData->Result() as $Draft) { 6 | $Offset = GetValue('CountComments', $Draft, 0); 7 | if($Offset > C('Vanilla.Comments.PerPage', 30)) { 8 | $Offset -= C('Vanilla.Comments.PerPage', 30); 9 | } else { 10 | $Offset = 0; 11 | } 12 | 13 | $EditUrl = !is_numeric($Draft->DiscussionID) || $Draft->DiscussionID <= 0 ? '/post/editdiscussion/0/'.$Draft->DraftID : '/discussion/'.$Draft->DiscussionID.'/'.$Offset.'/#Form_Comment'; 14 | $Alt = $Alt == ' Alt' ? '' : ' Alt'; 15 | $Excerpt = SliceString(Gdn_Format::Text($Draft->Body), 200); 16 | ?> 17 |
  • 18 |
    DraftID.'/'.$Session->TransientKey().'?Target='.urlencode($this->SelfUrl), 'Delete'); ?>
    19 |
    20 | Name, FALSE), $EditUrl, 'Title DraftLink'); ?> 21 | 22 | 23 |
    24 | 25 |
    26 | 27 | 28 |
    29 |
  • 30 | install(); 37 | $this->info( 38 | 'Vanilla now connected to Laravel. Try it out at ' . 39 | \URL::to(forum_get_route_prefix()) 40 | ); 41 | } 42 | 43 | /** 44 | * Get the console command arguments. 45 | * 46 | * @return array 47 | */ 48 | protected function getArguments() 49 | { 50 | return []; 51 | } 52 | 53 | /** 54 | * Get the console command options. 55 | * 56 | * @return array 57 | */ 58 | protected function getOptions() 59 | { 60 | return []; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/views/themes/default/views/discussions/archives.php: -------------------------------------------------------------------------------- 1 | FetchViewLocation('helper_functions'); 3 | ?> 4 | 5 |

    Data('Title'); ?>

    6 |
    7 | Data('_Description'); 9 | ?> 10 |
    11 | 12 |
    13 | 16 |
    17 | 18 | FetchViewLocation('table_functions'); 22 | ?> 23 |
    24 | 25 | 26 | 29 | 30 | 31 | DiscussionData->Result() as $Discussion) { 33 | WriteDiscussionRow($Discussion, $this, Gdn::Session(), FALSE); 34 | } 35 | ?> 36 | 37 |
    38 |
    39 | 42 |
      43 | FetchViewLocation('discussions')); ?> 44 |
    45 | 49 |
    50 | 53 |
    -------------------------------------------------------------------------------- /src/migrations/2014_09_23_194713_create_GDN_Message_table.php: -------------------------------------------------------------------------------- 1 | integer('MessageID', true); 18 | $table->text('Content'); 19 | $table->string('Format', 20)->nullable(); 20 | $table->boolean('AllowDismiss')->default(1); 21 | $table->boolean('Enabled')->default(1); 22 | $table->string('Application', 255)->nullable(); 23 | $table->string('Controller', 255)->nullable(); 24 | $table->string('Method', 255)->nullable(); 25 | $table->integer('CategoryID')->nullable(); 26 | $table->boolean('IncludeSubcategories')->default(0); 27 | $table->string('AssetTarget', 20)->nullable(); 28 | $table->string('CssClass', 20)->nullable(); 29 | $table->integer('Sort')->nullable(); 30 | }); 31 | } 32 | 33 | 34 | /** 35 | * Reverse the migrations. 36 | * 37 | * @return void 38 | */ 39 | public function down() 40 | { 41 | Schema::drop('GDN_Message'); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/views/themes/default/views/moderation/confirmdiscussiondeletes.php: -------------------------------------------------------------------------------- 1 | 2 |

    Data('Title'); ?>

    3 | Form->Open(); 5 | echo $this->Form->Errors(); 6 | 7 | $CountAllowed = GetValue('CountAllowed', $this->Data, 0); 8 | $CountNotAllowed = GetValue('CountNotAllowed', $this->Data, 0); 9 | $CountCheckedDiscussions = GetValue('CountCheckedDiscussions', $this->Data, 0); 10 | 11 | if ($CountNotAllowed > 0) { 12 | echo Wrap(sprintf( 13 | T('NoPermissionToDeleteDiscussions', 'You do not have permission to delete %1$s of the selected discussions.'), 14 | $CountNotAllowed 15 | ), 'p'); 16 | 17 | echo Wrap(sprintf( 18 | T('AboutToDeleteSelectedDiscussions', 'You are about to delete %1$s of the %2$s selected discussions.'), 19 | $CountAllowed, 20 | $CountCheckedDiscussions 21 | ), 'p'); 22 | } else { 23 | echo Wrap(sprintf( 24 | T('AboutToDelete', 'You are about to delete %s.'), 25 | Plural($CountAllowed, '%s discussion', '%s discussions') 26 | ), 'p'); 27 | } 28 | 29 | echo '

    '.T('Are you sure you wish to continue?').'

    '; 30 | 31 | echo '
    ', 32 | $this->Form->Button('OK', array('class' => 'Button Primary')), 33 | $this->Form->Button('Cancel', array('type' => 'button', 'class' => 'Button Close')), 34 | '
    '; 35 | 36 | echo $this->Form->Close(); 37 | -------------------------------------------------------------------------------- /src/migrations/2014_09_23_194713_create_GDN_UserConversation_table.php: -------------------------------------------------------------------------------- 1 | integer('UserID'); 18 | $table->integer('ConversationID')->index('FK_UserConversation_ConversationID'); 19 | $table->integer('CountReadMessages')->default(0); 20 | $table->integer('LastMessageID')->nullable(); 21 | $table->dateTime('DateLastViewed')->nullable(); 22 | $table->dateTime('DateCleared')->nullable(); 23 | $table->boolean('Bookmarked')->default(0); 24 | $table->boolean('Deleted')->default(0); 25 | $table->dateTime('DateConversationUpdated')->nullable(); 26 | $table->primary(['UserID','ConversationID']); 27 | $table->index(['UserID','Deleted','DateConversationUpdated'], 'IX_UserConversation_Inbox'); 28 | }); 29 | } 30 | 31 | 32 | /** 33 | * Reverse the migrations. 34 | * 35 | * @return void 36 | */ 37 | public function down() 38 | { 39 | Schema::drop('GDN_UserConversation'); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/models/Draft.php: -------------------------------------------------------------------------------- 1 | 'exists:GDN_Discussion,DiscussionID', 10 | 'CategoryID' => 'exists:GDN_Category,CategoryID', 11 | 'Name' => 'max:100', 12 | 'Tags' => 'max:255', 13 | 'Closed' => 'boolean', 14 | 'Announce' => 'boolean', 15 | 'Sink' => 'boolean', 16 | 'Body' => 'required', 17 | 'Format' => 'max:20', 18 | ]; 19 | 20 | // auditing 21 | use AuditingTrait; 22 | public function getAuditors() 23 | { 24 | return [ 25 | 'InsertUserID', 'DateInserted', 26 | 'UpdateUserID', 'DateUpdated', 27 | ]; 28 | } 29 | 30 | // definitions 31 | protected $table = 'GDN_Draft'; 32 | protected $primaryKey = 'DraftID'; 33 | 34 | public function getDates() 35 | { 36 | return [ 'DateInserted', 'DateUpdated', ]; 37 | } 38 | 39 | // relations 40 | public function discussion() 41 | { 42 | return $this->hasOne( 43 | '\BishopB\Forum\Discussion', 'DiscussionID', 'DiscussionID' 44 | ); 45 | } 46 | 47 | public function category() 48 | { 49 | return $this->hasOne( 50 | '\BishopB\Forum\Category', 'CategoryID', 'CategoryID' 51 | ); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/migrations/2014_09_23_194713_create_GDN_Draft_table.php: -------------------------------------------------------------------------------- 1 | integer('DraftID', true); 18 | $table->integer('DiscussionID')->nullable()->index('FK_Draft_DiscussionID'); 19 | $table->integer('CategoryID')->nullable()->index('FK_Draft_CategoryID'); 20 | $table->integer('InsertUserID')->index('FK_Draft_InsertUserID'); 21 | $table->integer('UpdateUserID'); 22 | $table->string('Name', 100)->nullable(); 23 | $table->string('Tags', 255)->nullable(); 24 | $table->boolean('Closed')->default(0); 25 | $table->boolean('Announce')->default(0); 26 | $table->boolean('Sink')->default(0); 27 | $table->text('Body'); 28 | $table->string('Format', 20)->nullable(); 29 | $table->dateTime('DateInserted'); 30 | $table->dateTime('DateUpdated')->nullable(); 31 | }); 32 | } 33 | 34 | 35 | /** 36 | * Reverse the migrations. 37 | * 38 | * @return void 39 | */ 40 | public function down() 41 | { 42 | Schema::drop('GDN_Draft'); 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/views/themes/default/views/categories/discussions.php: -------------------------------------------------------------------------------- 1 | '.$this->Data('Title').''; 3 | $ViewLocation = $this->FetchViewLocation('discussions', 'discussions'); 4 | ?> 5 |
    6 | CategoryData->Result() as $Category) : 7 | if ($Category->CategoryID <= 0) 8 | continue; 9 | 10 | $this->Category = $Category; 11 | $this->DiscussionData = $this->CategoryDiscussionData[$Category->CategoryID]; 12 | 13 | if ($this->DiscussionData->NumRows() > 0) : ?> 14 | 15 |
    16 |

    Name), CategoryUrl($Category)); 18 | Gdn::Controller()->EventArguments['Category'] = $Category; 19 | Gdn::Controller()->FireEvent('AfterCategoryTitle'); 20 | ?>

    21 | 22 |
      23 | FetchViewLocation('discussions', 'discussions')); ?> 24 |
    25 | 26 | DiscussionData->NumRows() == $this->DiscussionsPerCategory) : ?> 27 |
    28 | UrlCode); ?> 29 |
    30 | 31 | 32 |
    33 | 34 | 35 | 36 | 37 |
    -------------------------------------------------------------------------------- /src/views/themes/default/views/default.master.tpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {asset name="Head"} 5 | 6 | 7 |
    8 | 23 |
    24 |
    25 | 26 |
    27 | {module name="MeModule"} 28 | {asset name="Panel"} 29 |
    30 |
    {asset name="Content"}
    31 |
    32 |
    33 | 39 |
    40 | {event name="AfterBody"} 41 | 42 | 43 | -------------------------------------------------------------------------------- /src/migrations/2014_09_23_194713_create_GDN_Attachment_table.php: -------------------------------------------------------------------------------- 1 | integer('AttachmentID', true); 18 | $table->string('Type', 64); 19 | $table->string('ForeignID', 50)->index('IX_Attachment_ForeignID'); 20 | $table->integer('ForeignUserID')->index('FK_Attachment_ForeignUserID'); 21 | $table->string('Source', 64); 22 | $table->string('SourceID', 32); 23 | $table->string('SourceURL', 255); 24 | $table->text('Attributes')->nullable(); 25 | $table->dateTime('DateInserted'); 26 | $table->integer('InsertUserID')->index('FK_Attachment_InsertUserID'); 27 | $table->string('InsertIPAddress', 64); 28 | $table->dateTime('DateUpdated')->nullable(); 29 | $table->integer('UpdateUserID')->nullable(); 30 | $table->string('UpdateIPAddress', 15)->nullable(); 31 | }); 32 | } 33 | 34 | 35 | /** 36 | * Reverse the migrations. 37 | * 38 | * @return void 39 | */ 40 | public function down() 41 | { 42 | Schema::drop('GDN_Attachment'); 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/ForumServiceProvider.php: -------------------------------------------------------------------------------- 1 | package('bishopb/laravel-forums', 'forum', __DIR__); 17 | 18 | require_once __DIR__ . '/boot/helpers.php'; 19 | require_once __DIR__ . '/boot/routes.php'; 20 | 21 | $this->commands('forum::commands.migrate', 'forum::commands.connect'); 22 | } 23 | 24 | /** 25 | * Register the service provider. Keep it fast. 26 | * 27 | * @return void 28 | */ 29 | public function register() 30 | { 31 | $this->app->register( 32 | 'Felixkiss\UniqueWithValidator\UniqueWithValidatorServiceProvider' 33 | ); 34 | 35 | // providers 36 | $this->app->bind( 37 | 'BishopB\Forum\UserMapperInterface', 'BishopB\Forum\UserMapperAllGuestAccess' 38 | ); 39 | 40 | // commands 41 | $this->app['forum::commands.migrate'] = $this->app->share(function ($app) { 42 | return new VanillaMigrate(); 43 | }); 44 | $this->app['forum::commands.connect'] = $this->app->share(function ($app) { 45 | return new VanillaConnect(); 46 | }); 47 | } 48 | 49 | /** 50 | * We have views and configuration: can't defer. 51 | * 52 | * @var bool 53 | */ 54 | protected $defer = false; 55 | } 56 | -------------------------------------------------------------------------------- /src/migrations/2014_09_23_194713_create_GDN_Media_table.php: -------------------------------------------------------------------------------- 1 | integer('MediaID', true); 18 | $table->string('Name', 255); 19 | $table->string('Path', 255); 20 | $table->string('Type', 128); 21 | $table->integer('Size'); 22 | $table->integer('InsertUserID'); 23 | $table->dateTime('DateInserted'); 24 | $table->integer('ForeignID')->nullable(); 25 | $table->string('ForeignTable', 24)->nullable(); 26 | $table->smallInteger('ImageWidth')->unsigned()->nullable(); 27 | $table->smallInteger('ImageHeight')->unsigned()->nullable(); 28 | $table->smallInteger('ThumbWidth')->unsigned()->nullable(); 29 | $table->smallInteger('ThumbHeight')->unsigned()->nullable(); 30 | $table->string('ThumbPath', 255)->nullable(); 31 | $table->index(['ForeignID','ForeignTable'], 'IX_Media_Foreign'); 32 | }); 33 | } 34 | 35 | 36 | /** 37 | * Reverse the migrations. 38 | * 39 | * @return void 40 | */ 41 | public function down() 42 | { 43 | Schema::drop('GDN_Media'); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/views/themes/default/views/moderation/confirmdiscussionmoves.php: -------------------------------------------------------------------------------- 1 | 2 |

    Data('Title'); ?>

    3 | Form->Open(); 5 | echo $this->Form->Errors(); 6 | 7 | $CountAllowed = GetValue('CountAllowed', $this->Data, 0); 8 | $CountNotAllowed = GetValue('CountNotAllowed', $this->Data, 0); 9 | $CountCheckedDiscussions = GetValue('CountCheckedDiscussions', $this->Data, 0); 10 | 11 | if ($CountNotAllowed > 0) { 12 | echo Wrap(sprintf( 13 | t('You do not have permission to move %1$s of the selected discussions.'), 14 | $CountNotAllowed 15 | ), 'p'); 16 | 17 | echo Wrap(sprintf( 18 | t('You are about to move %1$s of the %2$s of the selected discussions.'), 19 | $CountAllowed, 20 | $CountCheckedDiscussions 21 | ), 'p'); 22 | } else { 23 | echo Wrap(sprintf( 24 | t('You are about to move %s.'), 25 | Plural($CountCheckedDiscussions, '%s discussion', '%s discussions') 26 | ), 'p'); 27 | } 28 | ?> 29 |
      30 |
    • 31 |
      '; 33 | echo $this->Form->Label('Category', 'CategoryID'), ' '; 34 | echo $this->Form->CategoryDropDown(); 35 | echo '

      '; 36 | ?> 37 |
    • 38 |
    • 39 | '. 41 | $this->Form->CheckBox('RedirectLink', 'Leave a redirect link.'). 42 | '

      '; 43 | ?> 44 |
    • 45 |
    46 | Form->Close('Move'); 48 | -------------------------------------------------------------------------------- /src/migrations/2014_09_23_194713_create_GDN_UserAuthenticationProvider_table.php: -------------------------------------------------------------------------------- 1 | string('AuthenticationKey', 64)->primary(); 18 | $table->string('AuthenticationSchemeAlias', 32); 19 | $table->string('Name', 50)->nullable(); 20 | $table->string('URL')->nullable(); 21 | $table->text('AssociationSecret')->nullable(); 22 | $table->string('AssociationHashMethod', 20)->nullable(); 23 | $table->string('AuthenticateUrl')->nullable(); 24 | $table->string('RegisterUrl')->nullable(); 25 | $table->string('SignInUrl')->nullable(); 26 | $table->string('SignOutUrl')->nullable(); 27 | $table->string('PasswordUrl')->nullable(); 28 | $table->string('ProfileUrl')->nullable(); 29 | $table->text('Attributes')->nullable(); 30 | $table->boolean('Active')->default(1); 31 | $table->boolean('IsDefault')->default(0); 32 | }); 33 | } 34 | 35 | 36 | /** 37 | * Reverse the migrations. 38 | * 39 | * @return void 40 | */ 41 | public function down() 42 | { 43 | Schema::drop('GDN_UserAuthenticationProvider'); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/models/Log.php: -------------------------------------------------------------------------------- 1 | 'required|in:Delete,Edit,Spam,Moderate,Pending,Ban,Error', 10 | 'RecordType' => 'required|in:Discussion,Comment,User,Registration,Activity,ActivityComment,Configuration,Group', 11 | 'TransactionLogID' => 'integer', 12 | 'RecordID' => 'integer', 13 | 'RecordUserID' => 'exists:GDN_User,UserID', 14 | 'RecordDate' => 'required|date', 15 | 'RecordIPAddress' => 'ip|max:15', 16 | 'OtherUserIDs' => 'max:255', 17 | 'ParentRecordID' => 'integer', 18 | 'CategoryID' => 'exists:GDN_Category,CategoryID', 19 | 'Data' => none, 20 | 'CountGroup' => 'integer', 21 | ]; 22 | 23 | // auditing 24 | use AuditingTrait; 25 | public function getAuditors() 26 | { 27 | return [ 28 | 'InsertUserID', 'DateInserted', 'InsertIPAddress', 29 | 'DateUpdated', 30 | ]; 31 | } 32 | 33 | // definitions 34 | protected $table = 'GDN_Log'; 35 | protected $primaryKey = 'LogID'; 36 | 37 | public function getDates() 38 | { 39 | return [ 'DateInserted', 'DateUpdated', 'RecordDate', ]; 40 | } 41 | 42 | // relations 43 | public function record_user() 44 | { 45 | return $this->hasOne('\BishopB\Forum\User', 'UserID', 'RecordUserID'); 46 | } 47 | 48 | public function category() 49 | { 50 | return $this->hasOne('\BishopB\Forum\Category', 'CategoryID', 'CategoryID'); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/models/AuditingTrait.php: -------------------------------------------------------------------------------- 1 | getAuditors())) { 33 | return $this->hasOne('\BishopB\Forum\User', 'UserID', 'InsertUserID'); 34 | } else { 35 | return false; 36 | } 37 | } 38 | 39 | public function updating_user() 40 | { 41 | if (in_array('UpdateUserID', $this->getAuditors())) { 42 | return $this->hasOne('\BishopB\Forum\User', 'UserID', 'UpdateUserID'); 43 | } else { 44 | return false; 45 | } 46 | } 47 | 48 | public function deleting_user() 49 | { 50 | if (in_array('DeleteUserID', $this->getAuditors())) { 51 | return $this->hasOne('\BishopB\Forum\User', 'UserID', 'DeleteUserID'); 52 | } else { 53 | return false; 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/views/themes/default/views/discussions/popin.php: -------------------------------------------------------------------------------- 1 | 2 |
      3 | Data('Discussions'))): 5 | ?> 6 |
    • 7 | Data('Title'), 'strong'); ?> 8 |
    • 9 | Data('Discussions') as $Row): 11 | ?> 12 |
    • 13 |
      'First')); ?>
      14 |
      15 | Name, $Row->Url.'#latest'); ?> 16 |
      17 | '.Plural($Row->CountComments, '%s comment', '%s comments').' '; 19 | 20 | if ($Row->CountUnreadComments === TRUE) { 21 | echo ' '.T('new').' '; 22 | } elseif ($Row->CountUnreadComments > 0) { 23 | echo ' '.Plural($Row->CountUnreadComments, '%s new', '%s new plural').' '; 24 | } 25 | 26 | echo ' '.Gdn_Format::Date($Row->DateLastComment).' '; 27 | ?> 28 |
      29 |
      30 |
    • 31 | 32 |
    • 33 | 36 |
    • 37 | 38 |
    • 39 | 40 |
    -------------------------------------------------------------------------------- /src/services/GardenSmarty.php: -------------------------------------------------------------------------------- 1 | Smarty(); 18 | 19 | // stuff all the facades into Smarty 20 | $loader = \Illuminate\Foundation\AliasLoader::getInstance(); 21 | foreach ($loader->getAliases() as $alias => $class) { 22 | $object = $this->resolve($class); 23 | $smarty->assign($alias, $object); 24 | } 25 | } 26 | 27 | /** 28 | * Yanked from davejamesmiller/laravel-aliases 29 | */ 30 | protected function resolve($class) 31 | { 32 | if ($this->isFacade($class)) { 33 | if ($accessor = $this->getFacadeAccessor($class)) { 34 | return \App::make($accessor); 35 | } else { 36 | return $class::getFacadeRoot(); 37 | } 38 | } 39 | 40 | return null; 41 | } 42 | 43 | protected function isFacade($class) 44 | { 45 | return get_parent_class($class) == 'Illuminate\Support\Facades\Facade'; 46 | } 47 | 48 | protected function getFacadeAccessor($class) 49 | { 50 | // HACK!! 51 | $method = new \ReflectionMethod($class, 'getFacadeAccessor'); 52 | $method->setAccessible(true); 53 | $accessor = $method->invoke(null); 54 | 55 | // Some facades return an object not a name, e.g. Illuminate\Support\Facades\Blade 56 | return is_string($accessor) ? $accessor : null; 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/commands/VanillaMigrate.php: -------------------------------------------------------------------------------- 1 | input->getOptions() as $option => $value) { 37 | if (! empty($value)) { 38 | $options['--' . $option] = $value; 39 | } 40 | } 41 | 42 | $options['--package'] = 'bishopb/laravel-forums'; 43 | 44 | $this->call('migrate', $options); 45 | } 46 | 47 | /** 48 | * Get the console command arguments. 49 | * 50 | * @return array 51 | */ 52 | protected function getArguments() 53 | { 54 | return []; 55 | } 56 | 57 | /** 58 | * Get the console command options. 59 | * 60 | * @return array 61 | */ 62 | protected function getOptions() 63 | { 64 | $o = InputOption::VALUE_OPTIONAL; 65 | $n = InputOption::VALUE_NONE; 66 | return [ 67 | [ 'database', null, $o, 'The database connection to use.' ], 68 | [ 'force', null, $n, 'Force the operation to run when in production.' ], 69 | [ 'pretend', null, $n, 'Dump the SQL queries that would be run.' ], 70 | ]; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/migrations/2014_09_23_194713_create_GDN_Conversation_table.php: -------------------------------------------------------------------------------- 1 | integer('ConversationID', true); 18 | $table->string('Type', 10)->nullable()->index('IX_Conversation_Type'); 19 | $table->string('ForeignID', 40)->nullable(); 20 | $table->string('Subject', 100)->nullable(); 21 | $table->string('Contributors', 255); 22 | $table->integer('FirstMessageID')->nullable()->index('FK_Conversation_FirstMessageID'); 23 | $table->integer('InsertUserID')->index('FK_Conversation_InsertUserID'); 24 | $table->dateTime('DateInserted')->nullable()->index('FK_Conversation_DateInserted'); 25 | $table->string('InsertIPAddress', 15)->nullable(); 26 | $table->integer('UpdateUserID')->index('FK_Conversation_UpdateUserID'); 27 | $table->dateTime('DateUpdated'); 28 | $table->string('UpdateIPAddress', 15)->nullable(); 29 | $table->integer('CountMessages')->default(0); 30 | $table->integer('CountParticipants')->default(0); 31 | $table->integer('LastMessageID')->nullable(); 32 | $table->integer('RegardingID')->nullable()->index('IX_Conversation_RegardingID'); 33 | }); 34 | } 35 | 36 | 37 | /** 38 | * Reverse the migrations. 39 | * 40 | * @return void 41 | */ 42 | public function down() 43 | { 44 | Schema::drop('GDN_Conversation'); 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/views/themes/default/views/discussions/index.php: -------------------------------------------------------------------------------- 1 | FetchViewLocation('helper_functions', 'discussions', 'vanilla'); 4 | 5 | echo '

    '. 6 | AdminCheck(NULL, array('', ' ')). 7 | $this->Data('Title'). 8 | '

    '; 9 | 10 | if ($Description = $this->Description()) { 11 | echo Wrap($Description, 'div', array('class' => 'P PageDescription')); 12 | } 13 | 14 | $this->FireEvent('AfterPageTitle'); 15 | 16 | include $this->FetchViewLocation('Subtree', 'Categories', 'Vanilla'); 17 | 18 | $this->FireEvent('AfterCategorySubtree'); 19 | 20 | $PagerOptions = array('Wrapper' => ' 
    %2$s
    ', 'RecordCount' => $this->Data('CountDiscussions'), 'CurrentRecords' => $this->Data('Discussions')->NumRows()); 21 | if ($this->Data('_PagerUrl')) 22 | $PagerOptions['Url'] = $this->Data('_PagerUrl'); 23 | 24 | echo '
    '; 25 | PagerModule::Write($PagerOptions); 26 | echo Gdn_Theme::Module('NewDiscussionModule', $this->Data('_NewDiscussionProperties', array('CssClass' => 'Button Action Primary'))); 27 | echo '
    '; 28 | 29 | if ($this->DiscussionData->NumRows() > 0 || (isset($this->AnnounceData) && is_object($this->AnnounceData) && $this->AnnounceData->NumRows() > 0)) { 30 | ?> 31 |
      32 | FetchViewLocation('discussions', 'Discussions', 'Vanilla')); ?> 33 |
    34 | '; 37 | PagerModule::Write($PagerOptions); 38 | echo Gdn_Theme::Module('NewDiscussionModule', $this->Data('_NewDiscussionProperties', array('CssClass' => 'Button Action Primary'))); 39 | echo '
    '; 40 | 41 | } else { 42 | ?> 43 |
    44 | integer('LogID', true); 18 | $table->enum('Operation', array('Delete','Edit','Spam','Moderate','Pending','Ban','Error'))->index('IX_Log_Operation'); 19 | $table->enum('RecordType', array('Discussion','Comment','User','Registration','Activity','ActivityComment','Configuration','Group'))->index('IX_Log_RecordType'); 20 | $table->integer('TransactionLogID')->nullable(); 21 | $table->integer('RecordID')->nullable()->index('IX_Log_RecordID'); 22 | $table->integer('RecordUserID')->nullable(); 23 | $table->dateTime('RecordDate'); 24 | $table->string('RecordIPAddress', 15)->nullable()->index('IX_Log_RecordIPAddress'); 25 | $table->integer('InsertUserID'); 26 | $table->dateTime('DateInserted'); 27 | $table->string('InsertIPAddress', 15)->nullable(); 28 | $table->string('OtherUserIDs', 255)->nullable(); 29 | $table->dateTime('DateUpdated')->nullable(); 30 | $table->integer('ParentRecordID')->nullable()->index('IX_Log_ParentRecordID'); 31 | $table->integer('CategoryID')->nullable()->index('FK_Log_CategoryID'); 32 | $table->text('Data')->nullable(); 33 | $table->integer('CountGroup')->nullable(); 34 | }); 35 | } 36 | 37 | 38 | /** 39 | * Reverse the migrations. 40 | * 41 | * @return void 42 | */ 43 | public function down() 44 | { 45 | Schema::drop('GDN_Log'); 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/views/themes/default/views/modules/categories.php: -------------------------------------------------------------------------------- 1 | _Sender->CategoryID) ? $this->_Sender->CategoryID : ''; 4 | $OnCategories = strtolower($this->_Sender->ControllerName) == 'categoriescontroller' && !is_numeric($CategoryID); 5 | if ($this->Data !== FALSE) { 6 | foreach ($this->Data->Result() as $Category) { 7 | $CountDiscussions = $CountDiscussions + $Category->CountDiscussions; 8 | } 9 | ?> 10 |
    11 | 12 | 43 |
    44 | 'max:10', 10 | 'ForeignID' => 'max:40', 11 | 'Subject' => 'max:100', 12 | 'Contributors' => 'required|max:255', 13 | 'FirstMessageID' => 'exists:GDN_ConversationMessage,MessageID', 14 | 'CountMessages' => 'integer|min:0', 15 | 'CountParticipants' => 'integer|min:0', 16 | 'LastMessageID' => 'exists:GDN_ConversationMessage,MessageID', 17 | 'RegardingID' => 'exists:GDN_Regarding,RegardingID', 18 | ]; 19 | 20 | // auditing 21 | use AuditingTrait; 22 | public function getAuditors() 23 | { 24 | return [ 25 | 'InsertUserID', 'DateInserted', 'InsertIPAddress', 26 | 'UpdateUserID', 'DateUpdated', 'UpdateIPAddress', 27 | ]; 28 | } 29 | 30 | // definitions 31 | protected $table = 'GDN_Conversation'; 32 | protected $primaryKey = 'ConversationID'; 33 | 34 | public function getDates() 35 | { 36 | return [ 'DateInserted', 'DateUpdated', ]; 37 | } 38 | 39 | // relations 40 | public function messages() 41 | { 42 | return $this->hasMany( 43 | '\BishopB\Forum\ConversationMessage', 'ConversationID', 'ConversationID' 44 | ); 45 | } 46 | 47 | public function first_message() 48 | { 49 | return $this->hasOne( 50 | '\BishopB\Forum\ConversationMessage', 'MessageID', 'FirstMessageID' 51 | ); 52 | } 53 | 54 | public function last_message() 55 | { 56 | return $this->hasOne( 57 | '\BishopB\Forum\ConversationMessage', 'MessageID', 'LastMessageID' 58 | ); 59 | } 60 | 61 | public function regarding() 62 | { 63 | return $this->hasOne( 64 | '\BishopB\Forum\Regarding', 'RegardingID', 'RegardingID' 65 | ); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/views/themes/default/views/settings/deletecategory.php: -------------------------------------------------------------------------------- 1 | Form->Open(); 4 | echo $this->Form->Errors(); 5 | if (is_object($this->OtherCategories)) { 6 | ?> 7 |

    8 | 47 | Form->Close('Proceed'); 50 | } -------------------------------------------------------------------------------- /src/migrations/2014_09_23_194713_create_GDN_Activity_table.php: -------------------------------------------------------------------------------- 1 | integer('ActivityID', true); 18 | $table->integer('ActivityTypeID'); 19 | $table->integer('NotifyUserID')->default(0); 20 | $table->integer('ActivityUserID')->nullable(); 21 | $table->integer('RegardingUserID')->nullable(); 22 | $table->string('Photo', 255)->nullable(); 23 | $table->string('HeadlineFormat', 255)->nullable(); 24 | $table->text('Story')->nullable(); 25 | $table->string('Format', 10)->nullable(); 26 | $table->string('Route', 255)->nullable(); 27 | $table->string('RecordType', 20)->nullable(); 28 | $table->integer('RecordID')->nullable(); 29 | $table->integer('InsertUserID')->nullable()->index('FK_Activity_InsertUserID'); 30 | $table->dateTime('DateInserted'); 31 | $table->string('InsertIPAddress', 15)->nullable(); 32 | $table->dateTime('DateUpdated')->nullable()->index('IX_Activity_DateUpdated'); 33 | $table->boolean('Notified')->default(0); 34 | $table->boolean('Emailed')->default(0); 35 | $table->text('Data')->nullable(); 36 | $table->index(['NotifyUserID','Notified'], 'IX_Activity_Notify'); 37 | $table->index(['NotifyUserID','DateUpdated'], 'IX_Activity_Recent'); 38 | $table->index(['NotifyUserID','ActivityUserID','DateUpdated'], 'IX_Activity_Feed'); 39 | }); 40 | } 41 | 42 | 43 | /** 44 | * Reverse the migrations. 45 | * 46 | * @return void 47 | */ 48 | public function down() 49 | { 50 | Schema::drop('GDN_Activity'); 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/models/Activity.php: -------------------------------------------------------------------------------- 1 | 'required|exists:GDN_ActivityType,ActivityTypeID', 10 | 'NotifyUserID' => 'exists:GDN_User,UserID', 11 | 'ActivityUserID' => 'exists:GDN_User,UserID', 12 | 'RegardingUserID' => 'exists:GDN_User,UserID', 13 | 'Photo' => 'max:255', 14 | 'HeadlineFormat' => 'max:255', 15 | // 'Story' => none, 16 | 'Format' => 'max:10', 17 | 'Route' => 'max:255', 18 | 'RecordType' => 'max:20', 19 | 'RecordID' => 'integer', 20 | 'Notified' => 'boolean', 21 | 'Emailed' => 'boolean', 22 | // 'Data' => none, 23 | ]; 24 | 25 | // auditing 26 | use AuditingTrait; 27 | public function getAuditors() 28 | { 29 | return [ 30 | 'InsertUserID', 'DateInserted', 'InsertIPAddress', 31 | 'DateUpdated', 32 | ]; 33 | } 34 | 35 | // definitions 36 | protected $table = 'GDN_Activity'; 37 | protected $primaryKey = 'ActivityID'; 38 | 39 | public function getDates() 40 | { 41 | return [ 'DateInserted', 'DateUpdated', ]; 42 | } 43 | 44 | // relations 45 | public function type() 46 | { 47 | return $this->hasOne( 48 | '\BishopB\Forum\ActivityType', 'ActivityTypeID', 'ActivityTypeID' 49 | ); 50 | } 51 | 52 | public function comments() 53 | { 54 | return $this->hasMany( 55 | '\BishopB\Forum\ActivityComment', 'ActivityID', 'ActivityID' 56 | ); 57 | } 58 | 59 | public function user() 60 | { 61 | return $this->hasOne('\BishopB\Forum\User', 'UserID', 'ActivityUserID'); 62 | } 63 | 64 | public function user_to_notify() 65 | { 66 | 67 | } 68 | 69 | public function user_regarding() 70 | { 71 | return $this->hasOne('\BishopB\Forum\User', 'UserID', 'RegardingUserID'); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/views/themes/default/views/discussion/embed.php: -------------------------------------------------------------------------------- 1 | Data('Discussion'); 3 | $ForeignSource = $this->Data('ForeignSource'); 4 | $SortComments = $this->Data('SortComments'); 5 | $Comments = $this->Data('Comments', FALSE); 6 | $HasCommentData = $Comments !== FALSE; 7 | $Session = Gdn::Session(); 8 | if (!function_exists('WriteComment')) 9 | include($this->FetchViewLocation('helper_functions', 'discussion')); 10 | 11 | ?> 12 |
    13 | '; 15 | $this->FireEvent('CommentHeading'); 16 | echo ''; 17 | 18 | if ($SortComments == 'desc') 19 | WriteEmbedCommentForm(); 20 | else if ($HasCommentData && $Comments->NumRows() > 0) 21 | echo Wrap(T('Comments'), 'h2'); 22 | ?> 23 | 36 | Pager->LastPage()) { 39 | $LastCommentID = $this->AddDefinition('LastCommentID'); 40 | if(!$LastCommentID || $this->Data['Discussion']->LastCommentID > $LastCommentID) 41 | $this->AddDefinition('LastCommentID', (int)$this->Data['Discussion']->LastCommentID); 42 | $this->AddDefinition('Vanilla_Comments_AutoRefresh', Gdn::Config('Vanilla.Comments.AutoRefresh', 0)); 43 | } 44 | 45 | // Send the user to the discussion in the forum when paging 46 | if (C('Garden.Embed.PageToForum') && $this->Pager->HasMorePages()) { 47 | $DiscussionUrl = DiscussionUrl($Discussion).'#latest'; 48 | echo '
    '; 49 | echo Anchor(T('More Comments'), $DiscussionUrl); 50 | echo '
    '; 51 | } else 52 | echo $this->Pager->ToString('more'); 53 | } 54 | 55 | if ($SortComments != 'desc') 56 | WriteEmbedCommentForm(); 57 | 58 | ?> 59 |
    -------------------------------------------------------------------------------- /src/views/themes/default/views/categories/subtree.php: -------------------------------------------------------------------------------- 1 | Data('Category'); 4 | if (!$Category) 5 | return; 6 | 7 | $SubCategories = CategoryModel::MakeTree(CategoryModel::Categories(), $Category); 8 | 9 | if (!$SubCategories) 10 | return; 11 | 12 | require_once $this->FetchViewLocation('helper_functions', 'categories', 'vanilla'); 13 | 14 | ?> 15 | 16 | -------------------------------------------------------------------------------- /src/views/themes/default/views/discussion/index.php: -------------------------------------------------------------------------------- 1 | FetchViewLocation('helper_functions', 'discussion'); 5 | 6 | // Wrap the discussion related content in a div. 7 | echo '
    '; 8 | 9 | // Write the page title. 10 | echo ' 11 |
    '; 12 | 13 | echo '
    '; 14 | 15 | $this->FireEvent('BeforeDiscussionOptions'); 16 | WriteBookmarkLink(); 17 | WriteDiscussionOptions(); 18 | WriteAdminCheck(); 19 | 20 | echo '
    '; 21 | 22 | echo '

    '.$this->Data('Discussion.Name').'

    '; 23 | 24 | echo "
    \n\n"; 25 | 26 | $this->FireEvent('AfterDiscussionTitle'); 27 | $this->FireEvent('AfterPageTitle'); 28 | 29 | // Write the initial discussion. 30 | if ($this->Data('Page') == 1) { 31 | include $this->FetchViewLocation('discussion', 'discussion'); 32 | echo '
    '; // close discussion wrap 33 | 34 | $this->FireEvent('AfterDiscussion'); 35 | } else { 36 | echo '
    '; // close discussion wrap 37 | } 38 | 39 | echo '
    '; 40 | 41 | // Write the comments. 42 | $this->Pager->Wrapper = '%2$s'; 43 | echo ''; 44 | $this->FireEvent('CommentHeading'); 45 | echo $this->Pager->ToString('less'); 46 | echo ''; 47 | 48 | echo '
    '; 49 | if ($this->Data('Comments')->NumRows() > 0) 50 | echo '

    '.$this->Data('_CommentsHeader', T('Comments')).'

    '; 51 | ?> 52 | 55 | FireEvent('AfterComments'); 57 | if($this->Pager->LastPage()) { 58 | $LastCommentID = $this->AddDefinition('LastCommentID'); 59 | if(!$LastCommentID || $this->Data['Discussion']->LastCommentID > $LastCommentID) 60 | $this->AddDefinition('LastCommentID', (int)$this->Data['Discussion']->LastCommentID); 61 | $this->AddDefinition('Vanilla_Comments_AutoRefresh', Gdn::Config('Vanilla.Comments.AutoRefresh', 0)); 62 | } 63 | echo '
    '; 64 | 65 | echo '
    '; 66 | $this->Pager->Wrapper = '
    %2$s
    '; 67 | echo $this->Pager->ToString('more'); 68 | echo '
    '; 69 | echo '
    '; 70 | 71 | WriteCommentForm(); 72 | -------------------------------------------------------------------------------- /src/migrations/2014_09_23_194713_create_GDN_Comment_table.php: -------------------------------------------------------------------------------- 1 | getSchemaGrammar(); 16 | 17 | Schema::create('GDN_Comment', function (Blueprint $table) use ($grammar) 18 | { 19 | $table->integer('CommentID', true); 20 | $table->integer('DiscussionID'); 21 | $table->integer('InsertUserID')->nullable()->index('FK_Comment_InsertUserID'); 22 | $table->integer('UpdateUserID')->nullable(); 23 | $table->integer('DeleteUserID')->nullable(); 24 | $table->text('Body'); 25 | $table->string('Format', 20)->nullable(); 26 | $table->dateTime('DateInserted')->nullable()->index('IX_Comment_DateInserted'); 27 | $table->dateTime('DateDeleted')->nullable(); 28 | $table->dateTime('DateUpdated')->nullable(); 29 | $table->string('InsertIPAddress', 15)->nullable(); 30 | $table->string('UpdateIPAddress', 15)->nullable(); 31 | $table->boolean('Flag')->default(0); 32 | $table->float('Score', 10, 0)->nullable(); 33 | $table->text('Attributes')->nullable(); 34 | $table->index(['DiscussionID','DateInserted'], 'IX_Comment_1'); 35 | if ($grammar instanceof \Illuminate\Database\Schema\Grammars\MySqlGrammar) { 36 | $table->engine = 'MyISAM'; 37 | } 38 | }); 39 | 40 | if ($grammar instanceof \Illuminate\Database\Schema\Grammars\MySqlGrammar) { 41 | DB::statement('ALTER TABLE `GDN_Comment` ADD FULLTEXT search(Body)'); 42 | } 43 | } 44 | 45 | 46 | /** 47 | * Reverse the migrations. 48 | * 49 | * @return void 50 | */ 51 | public function down() 52 | { 53 | $grammar = Schema::getConnection()->getSchemaGrammar(); 54 | if ($grammar instanceof \Illuminate\Database\Schema\Grammars\MySqlGrammar) { 55 | Schema::table('GDN_Comment', function($table) { 56 | $table->dropIndex('search'); 57 | }); 58 | } 59 | Schema::drop('GDN_Comment'); 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /src/views/themes/default/views/settings/notificationpreferences.php: -------------------------------------------------------------------------------- 1 | 2 |

    3 |
    4 | 7 |
    8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | Data('CategoryNotifications') as $Category): 27 | $CategoryID = $Category['CategoryID']; 28 | 29 | if ($Category['Heading']): 30 | ?> 31 | 32 | 35 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 51 | 52 |
     
    33 | 34 | 36 |   37 |
    ">Form->CheckBox("Email.NewDiscussion.{$CategoryID}", '', array('value' => 1)); ?>Form->CheckBox("Popup.NewDiscussion.{$CategoryID}", '', array('value' => 1)); ?>Form->CheckBox("Email.NewComment.{$CategoryID}", '', array('value' => 1)); ?>Form->CheckBox("Popup.NewComment.{$CategoryID}", '', array('value' => 1)); ?>
    -------------------------------------------------------------------------------- /src/models/Category.php: -------------------------------------------------------------------------------- 1 | 'integer|min:-1', 13 | 'TreeLeft' => 'integer|min:0', 14 | 'TreeRight' => 'integer|min:0', 15 | 'Depth' => 'integer|min:0', 16 | 'CountDiscussions' => 'integer|min:0', 17 | 'CountComments' => 'integer|min:0', 18 | 'DateMarkedRead' => 'date', 19 | 'AllowDiscussions' => 'boolean', 20 | 'Archived' => 'boolean', 21 | 'Name' => 'required|max:255', 22 | 'UrlCode' => 'max:255', 23 | 'Description' => 'max:500', 24 | 'Sort' => 'integer', 25 | 'CssClass' => 'max:50', 26 | 'Photo' => 'max:255', 27 | 'PermissionCategoryID' => 'integer|min:-1|exists:GDN_Permission,PermissionID', 28 | 'PointsCategoryID' => 'integer', 29 | 'HideAllDiscussions' => 'boolean', 30 | 'DisplayAs' => 'in:Categories,Discussions,Default', 31 | 'LastCommentID' => 'exists:GDN_Comment,CommentID', 32 | 'LastDiscussionID' => 'exists:GDN_Discussion,DiscussionID', 33 | 'LastDateInserted' => 'date', 34 | 'AllowedDiscussionTypes' => 'max:255', 35 | 'DefaultDiscussionType' => 'max:10', 36 | ]; 37 | 38 | // auditing 39 | use AuditingTrait; 40 | public function getAuditors() 41 | { 42 | return [ 43 | 'InsertUserID', 'DateInserted', 'UpdateUserID', 'DateUpdated', 44 | ]; 45 | } 46 | 47 | // definitions 48 | protected $table = 'GDN_Category'; 49 | protected $primaryKey = 'CategoryID'; 50 | 51 | public function getDates() 52 | { 53 | return [ 'DateInserted', 'DateUpdated', ]; 54 | } 55 | 56 | // relations 57 | public function last_comment() 58 | { 59 | return $this->hasOne( 60 | '\BishopB\Forum\Comment', 'CommentID', 'LastCommentID' 61 | ); 62 | } 63 | 64 | public function last_discussion() 65 | { 66 | return $this->hasOne( 67 | '\BishopB\Forum\Discussion', 'DiscussionID', 'LastDiscussionID' 68 | ); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/migrations/2014_09_23_194713_create_GDN_Category_table.php: -------------------------------------------------------------------------------- 1 | integer('CategoryID', true); 18 | $table->integer('ParentCategoryID')->nullable(); 19 | $table->integer('TreeLeft')->nullable(); 20 | $table->integer('TreeRight')->nullable(); 21 | $table->integer('Depth')->nullable(); 22 | $table->integer('CountDiscussions')->default(0); 23 | $table->integer('CountComments')->default(0); 24 | $table->dateTime('DateMarkedRead')->nullable(); 25 | $table->boolean('AllowDiscussions')->default(1); 26 | $table->boolean('Archived')->default(0); 27 | $table->string('Name', 255); 28 | $table->string('UrlCode', 255)->nullable(); 29 | $table->string('Description', 500)->nullable(); 30 | $table->integer('Sort')->nullable(); 31 | $table->string('CssClass', 50)->nullable(); 32 | $table->string('Photo', 255)->nullable(); 33 | $table->integer('PermissionCategoryID')->default(-1); 34 | $table->integer('PointsCategoryID')->default(0); 35 | $table->boolean('HideAllDiscussions')->default(0); 36 | $table->enum('DisplayAs', array('Categories','Discussions','Default'))->default('Default'); 37 | $table->integer('InsertUserID')->index('FK_Category_InsertUserID'); 38 | $table->integer('UpdateUserID')->nullable(); 39 | $table->dateTime('DateInserted'); 40 | $table->dateTime('DateUpdated'); 41 | $table->integer('LastCommentID')->nullable(); 42 | $table->integer('LastDiscussionID')->nullable(); 43 | $table->dateTime('LastDateInserted')->nullable(); 44 | $table->string('AllowedDiscussionTypes', 255)->nullable(); 45 | $table->string('DefaultDiscussionType', 10)->nullable(); 46 | }); 47 | } 48 | 49 | 50 | /** 51 | * Reverse the migrations. 52 | * 53 | * @return void 54 | */ 55 | public function down() 56 | { 57 | Schema::drop('GDN_Category'); 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/views/themes/default/views/discussions/table.php: -------------------------------------------------------------------------------- 1 | FetchViewLocation('helper_functions', 'discussions', 'vanilla'); 8 | include_once $this->FetchViewLocation('table_functions', 'discussions', 'vanilla'); 9 | 10 | /** 11 | * Render the page. 12 | */ 13 | 14 | $PagerOptions = array('Wrapper' => '
    %2$s
    ', 'RecordCount' => $this->Data('CountDiscussions'), 'CurrentRecords' => $this->Data('Discussions')->NumRows()); 15 | if ($this->Data('_PagerUrl')) { 16 | $PagerOptions['Url'] = $this->Data('_PagerUrl'); 17 | } 18 | 19 | echo '

    '.$this->Data('Title').'

    '; 20 | 21 | if ($Description = $this->Data('_Description')) { 22 | echo '
    '; 23 | echo $this->Data('_Description', ' '); 24 | echo '
    '; 25 | } 26 | $this->FireEvent('AfterDescription'); 27 | 28 | include $this->FetchViewLocation('Subtree', 'Categories', 'Vanilla'); 29 | 30 | echo '
    '; 31 | PagerModule::Write($PagerOptions); 32 | echo Gdn_Theme::Module('NewDiscussionModule', $this->Data('_NewDiscussionProperties', array('CssClass' => 'Button Action Primary'))); 33 | echo '
    '; 34 | 35 | if ($this->DiscussionData->NumRows() > 0 || (isset($this->AnnounceData) && is_object($this->AnnounceData) && $this->AnnounceData->NumRows() > 0)) { 36 | ?> 37 |
    38 | 39 | 40 | 43 | 44 | 45 | AnnounceData)) { 48 | foreach ($this->AnnounceData->Result() as $Discussion) { 49 | $Alt = $Alt == ' Alt' ? '' : ' Alt'; 50 | WriteDiscussionRow($Discussion, $this, $Session, $Alt); 51 | } 52 | } 53 | 54 | $Alt = ''; 55 | foreach ($this->DiscussionData->Result() as $Discussion) { 56 | $Alt = $Alt == ' Alt' ? '' : ' Alt'; 57 | WriteDiscussionRow($Discussion, $this, $Session, $Alt); 58 | } 59 | ?> 60 | 61 |
    62 |
    63 | '; 66 | PagerModule::Write($PagerOptions); 67 | echo Gdn_Theme::Module('NewDiscussionModule', $this->Data('_NewDiscussionProperties', array('CssClass' => 'Button Action Primary')) ); 68 | echo ''; 69 | 70 | } else { 71 | ?> 72 |
    73 | getRoutes(), 27 | \App::make('request') 28 | ); 29 | }); 30 | 31 | // vanilla doesn't pass E_STRICT 32 | $old_error_reporting = error_reporting( 33 | E_ERROR|E_PARSE|E_CORE_ERROR| 34 | E_COMPILE_ERROR|E_USER_ERROR|E_RECOVERABLE_ERROR 35 | ); 36 | 37 | // define the constants we need to get going 38 | $this->define_constants(); 39 | 40 | // alright, boot it up 41 | require_once(PATH_ROOT . '/bootstrap.php'); 42 | 43 | // recover Laravel error handling 44 | \App::getFacadeRoot()->startExceptionHandling(); 45 | 46 | // do the requested work 47 | call_user_func($callback); 48 | 49 | // restore our environment as much as possible 50 | \App::bind('url', $old_url); 51 | error_reporting($old_error_reporting); 52 | } 53 | 54 | protected function define_constants() 55 | { 56 | $global_theme_path = __DIR__ . '/../views/themes'; 57 | $local_theme_path = app_path() . '/views/packages/bishopb/laravel-forums/themes'; 58 | 59 | $constants = [ 60 | 'APPLICATION' => 'Vanilla', 61 | 'APPLICATION_VERSION' => $this->get_vanilla_version(), 62 | 'DS' => '/', 63 | 'PATH_ROOT' => $this->get_vanilla_path(), 64 | 'PATH_CACHE' => storage_path() . '/cache', 65 | 'PATH_THEMES' => ( 66 | file_exists($local_theme_path) ? 67 | $local_theme_path : 68 | $global_theme_path 69 | ), 70 | 'PATH_UPLOADS' => \Config::get('forum::paths.uploads'), 71 | ]; 72 | 73 | foreach ($constants as $key => $val) { 74 | if (! defined($key)) { 75 | define($key, $val); 76 | } 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/models/Discussion.php: -------------------------------------------------------------------------------- 1 | 'max:10', 10 | 'ForeignID' => 'max:32', 11 | 'CategoryID' => 'required|exists:GDN_Category,CategoryID', 12 | 'FirstCommentID' => 'exists:GDN_Comment,CommentID', 13 | 'LastCommentID' => 'exists:GDN_Comment,CommentID', 14 | 'Name' => 'required|max:100', 15 | 'Body' => 'required', 16 | 'Format' => 'max:20', 17 | // 'Tags' => none, 18 | 'CountComments' => 'integer|min:0', 19 | 'CountBookmarks' => 'integer|min:0', 20 | 'CountViews' => 'integer|min:0', 21 | 'Closed' => 'boolean', 22 | 'Announce' => 'boolean', 23 | 'Sink' => 'boolean', 24 | 'DateLastComment' => 'date', 25 | 'LastCommentUserID' => 'exists:GDN_User,UserID', 26 | 'Score' => 'numeric', 27 | // 'Attributes' => none, 28 | 'RegardingID' => 'exists:GDN_Regarding,RegardingID', 29 | ]; 30 | 31 | // auditing 32 | use AuditingTrait; 33 | public function getAuditors() 34 | { 35 | return [ 36 | 'InsertUserID', 'DateInserted', 'InsertIPAddress', 37 | 'UpdateUserID', 'DateUpdated', 'UpdateIPAddress', 38 | ]; 39 | } 40 | 41 | // definitions 42 | protected $table = 'GDN_Discussion'; 43 | protected $primaryKey = 'DiscussionID'; 44 | 45 | public function getDates() 46 | { 47 | return [ 'DateInserted', 'DateUpdated', 'DateLastComment', ]; 48 | } 49 | 50 | // relations 51 | public function category() 52 | { 53 | return $this->hasOne( 54 | '\BishopB\Forum\Category', 'CategoryID', 'CategoryID' 55 | ); 56 | } 57 | 58 | public function comments() 59 | { 60 | return $this->hasMany( 61 | '\BishopB\Forum\Comment', 'DiscussionID', 'DiscussionID' 62 | ); 63 | } 64 | 65 | public function first_comment() 66 | { 67 | return $this->hasOne( 68 | '\BishopB\Forum\Comment', 'CommentID', 'FirstCommentID' 69 | ); 70 | } 71 | 72 | public function last_comment() 73 | { 74 | return $this->hasOne( 75 | '\BishopB\Forum\Comment', 'CommentID', 'LastCommentID' 76 | ); 77 | } 78 | 79 | public function last_commenting_user() 80 | { 81 | return $this->hasOne( 82 | '\BishopB\Forum\User', 'UserID', 'LastCommentUserID' 83 | ); 84 | } 85 | 86 | public function regarding() 87 | { 88 | return $this->hasOne( 89 | '\BishopB\Forum\Regarding', 'RegardingID', 'RegardingID' 90 | ); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/services/UserMapperSynchronicity.php: -------------------------------------------------------------------------------- 1 | setClosure([$this, 'dispatcher']); 46 | } 47 | 48 | public function dispatcher(\Illuminate\Auth\UserInterface $user = null) 49 | { 50 | // map the user ID: 1 is guest, otherwise add 100 51 | $vUID = (null === $user ? 1 : ($user->getKey() + $this->auth_user_offset)); 52 | 53 | // lookup the vanilla user with that ID 54 | $vUser = User::find($vUID); 55 | 56 | // not there, create 57 | if (null === $vUser) { 58 | if (null === $user) { 59 | if (is_callable($this->create_guest_account)) { 60 | $vUser = call_user_func($this->create_guest_account); 61 | } 62 | if (! $vUser instanceof User) { 63 | throw new NoVanillaUserMappedToGuest(); 64 | } 65 | } else { 66 | if (is_callable($this->create_account_for)) { 67 | $vUser = call_user_func($this->create_account_for, $vUID, $user); 68 | } 69 | if (! $vUser instanceof User) { 70 | throw new NoVanillaUserMappedToUser(); 71 | } 72 | } 73 | 74 | // update authenticated user data 75 | } else if (null !== $user && is_callable($this->update_account_for)) { 76 | call_user_func($this->update_account_for, $user, $vUser); 77 | } 78 | 79 | return $vUser; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/migrations/2014_09_23_194713_create_GDN_User_table.php: -------------------------------------------------------------------------------- 1 | integer('UserID', true); 18 | $table->string('Name', 50)->index('FK_User_Name'); 19 | $table->binary('Password', 100); 20 | $table->string('HashMethod', 10)->nullable(); 21 | $table->string('Photo', 255)->nullable(); 22 | $table->string('Title', 100)->nullable(); 23 | $table->string('Location', 100)->nullable(); 24 | $table->text('About')->nullable(); 25 | $table->string('Email', 200)->index('IX_User_Email'); 26 | $table->boolean('ShowEmail')->default(0); 27 | $table->enum('Gender', array('u','m','f'))->default('u'); 28 | $table->integer('CountVisits')->default(0); 29 | $table->integer('CountInvitations')->default(0); 30 | $table->integer('CountNotifications')->nullable(); 31 | $table->integer('InviteUserID')->nullable(); 32 | $table->text('DiscoveryText')->nullable(); 33 | $table->text('Preferences')->nullable(); 34 | $table->text('Permissions')->nullable(); 35 | $table->text('Attributes')->nullable(); 36 | $table->dateTime('DateSetInvitations')->nullable(); 37 | $table->dateTime('DateOfBirth')->nullable(); 38 | $table->dateTime('DateFirstVisit')->nullable(); 39 | $table->dateTime('DateLastActive')->nullable()->index('IX_User_DateLastActive'); 40 | $table->string('LastIPAddress', 15)->nullable(); 41 | $table->string('AllIPAddresses', 100)->nullable(); 42 | $table->dateTime('DateInserted')->index('IX_User_DateInserted'); 43 | $table->string('InsertIPAddress', 15)->nullable(); 44 | $table->dateTime('DateUpdated')->nullable(); 45 | $table->string('UpdateIPAddress', 15)->nullable(); 46 | $table->integer('HourOffset')->default(0); 47 | $table->float('Score', 10, 0)->nullable(); 48 | $table->boolean('Admin')->default(0); 49 | $table->boolean('Confirmed')->default(1); 50 | $table->boolean('Verified')->default(0); 51 | $table->boolean('Banned')->default(0); 52 | $table->boolean('Deleted')->default(0); 53 | $table->integer('Points')->default(0); 54 | $table->integer('CountUnreadConversations')->nullable(); 55 | $table->integer('CountDiscussions')->nullable(); 56 | $table->integer('CountUnreadDiscussions')->nullable(); 57 | $table->integer('CountComments')->nullable(); 58 | $table->integer('CountDrafts')->nullable(); 59 | $table->integer('CountBookmarks')->nullable(); 60 | }); 61 | } 62 | 63 | 64 | /** 65 | * Reverse the migrations. 66 | * 67 | * @return void 68 | */ 69 | public function down() 70 | { 71 | Schema::drop('GDN_User'); 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /src/models/AuditingObserver.php: -------------------------------------------------------------------------------- 1 | auth = $auth; 15 | $this->request = $request; 16 | } 17 | 18 | /** 19 | * Register the creating event for creating the model. 20 | * 21 | * @param \Illuminate\Database\Eloquent\Model $model 22 | */ 23 | public function creating(\Illuminate\Database\Eloquent\Model $model) 24 | { 25 | if ($this->needs($model, 'InsertUserID')) { 26 | $model->InsertUserID = $this->auth->user()->getKey(); 27 | if ($this->needs($model, 'UpdateUserID')) { 28 | $model->UpdateUserID = $model->InsertUserID; 29 | } 30 | } 31 | if ($this->needs($model, 'DateInserted')) { 32 | $model->DateInserted = date('Y-m-d H:i:s'); 33 | if ($this->needs($model, 'DateUpdated')) { 34 | $model->DateUpdated = $model->DateInserted; 35 | } 36 | } 37 | if ($this->needs($model, 'InsertIPAddress')) { 38 | $model->InsertIPAddress = $this->request->getClientIp(); 39 | if ($this->needs($model, 'UpdateIPAddress')) { 40 | $model->UpdateIPAddress = $model->InsertIPAddress; 41 | } 42 | } 43 | } 44 | 45 | /** 46 | * Register the updating event for updating the model. 47 | * 48 | * @param \Illuminate\Database\Eloquent\Model $model 49 | */ 50 | public function updating(\Illuminate\Database\Eloquent\Model $model) 51 | { 52 | if ($this->needs($model, 'UpdateUserID')) { 53 | $model->UpdateUserID = $this->auth->user()->getKey(); 54 | } 55 | if ($this->needs($model, 'DateUpdated')) { 56 | $model->DateUpdated = date('Y-m-d H:i:s'); 57 | } 58 | if ($this->needs($model, 'UpdateIPAddress')) { 59 | $model->UpdateIPAddress = $this->request->getClientIp(); 60 | } 61 | } 62 | 63 | /** 64 | * Register the deleting event for deleting the model. 65 | * 66 | * @param \Illuminate\Database\Eloquent\Model $model 67 | */ 68 | public function deleting(\Illuminate\Database\Eloquent\Model $model) 69 | { 70 | if ($this->needs($model, 'DeleteUserID')) { 71 | $model->DeleteUserID = $this->auth->user()->getKey(); 72 | } 73 | if ($this->needs($model, 'DateDeleted')) { 74 | $model->DateDeleted = date('Y-m-d H:i:s'); 75 | } 76 | } 77 | 78 | // PROTECTED API 79 | 80 | /** 81 | * Test whether a particular auditing attribute is needed. 82 | * 83 | * @param \Illuminate\Database\Eloquent\Model $model 84 | * @param string $attribute 85 | */ 86 | protected function needs(\Illuminate\Database\Eloquent\Model $model, $attribute) 87 | { 88 | return ( 89 | ( 90 | in_array($attribute, $model->getAuditors()) && // audit column in model & 91 | ! $model->getAttribute($attribute) // column not already set 92 | ) ? 93 | true : 94 | false 95 | ); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/migrations/2014_09_23_194713_create_GDN_Discussion_table.php: -------------------------------------------------------------------------------- 1 | getSchemaGrammar(); 16 | 17 | Schema::create('GDN_Discussion', function (Blueprint $table) use ($grammar) 18 | { 19 | $table->integer('DiscussionID', true); 20 | $table->string('Type', 10)->nullable()->index('IX_Discussion_Type'); 21 | $table->string('ForeignID', 32)->nullable()->index('IX_Discussion_ForeignID'); 22 | $table->integer('CategoryID'); 23 | $table->integer('InsertUserID')->index('FK_Discussion_InsertUserID'); 24 | $table->integer('UpdateUserID')->nullable(); 25 | $table->integer('FirstCommentID')->nullable(); 26 | $table->integer('LastCommentID')->nullable(); 27 | $table->string('Name', 100); 28 | $table->text('Body'); 29 | $table->string('Format', 20)->nullable(); 30 | $table->text('Tags')->nullable(); 31 | $table->integer('CountComments')->default(0); 32 | $table->integer('CountBookmarks')->nullable(); 33 | $table->integer('CountViews')->default(1); 34 | $table->boolean('Closed')->default(0); 35 | $table->boolean('Announce')->default(0); 36 | $table->boolean('Sink')->default(0); 37 | $table->dateTime('DateInserted')->index('IX_Discussion_DateInserted'); 38 | $table->dateTime('DateUpdated')->nullable(); 39 | $table->string('InsertIPAddress', 15)->nullable(); 40 | $table->string('UpdateIPAddress', 15)->nullable(); 41 | $table->dateTime('DateLastComment')->nullable()->index('IX_Discussion_DateLastComment'); 42 | $table->integer('LastCommentUserID')->nullable(); 43 | $table->float('Score', 10, 0)->nullable(); 44 | $table->text('Attributes')->nullable(); 45 | $table->integer('RegardingID')->nullable()->index('IX_Discussion_RegardingID'); 46 | $table->index(['CategoryID','DateLastComment'], 'IX_Discussion_CategoryPages'); 47 | $table->index(['CategoryID','DateInserted'], 'IX_Discussion_CategoryInserted'); 48 | 49 | if ($grammar instanceof \Illuminate\Database\Schema\Grammars\MySqlGrammar) { 50 | $table->engine = 'MyISAM'; 51 | } 52 | }); 53 | 54 | if ($grammar instanceof \Illuminate\Database\Schema\Grammars\MySqlGrammar) { 55 | DB::statement('ALTER TABLE `GDN_Discussion` ADD FULLTEXT search(Name,Body)'); 56 | } 57 | } 58 | 59 | 60 | /** 61 | * Reverse the migrations. 62 | * 63 | * @return void 64 | */ 65 | public function down() 66 | { 67 | $grammar = Schema::getConnection()->getSchemaGrammar(); 68 | if ($grammar instanceof \Illuminate\Database\Schema\Grammars\MySqlGrammar) { 69 | Schema::table('GDN_Discussion', function($table) { 70 | $table->dropIndex('search'); 71 | }); 72 | } 73 | 74 | Schema::drop('GDN_Discussion'); 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /src/models/User.php: -------------------------------------------------------------------------------- 1 | 'required|max:50', 10 | 'Password' => 'required|max:100', 11 | 'HashMethod' => 'in:crypt,django,drupal,ipb,joomla,mybb,phpbb,punbb,reset,random,smf,unknown,vanilla,vbulletin,webwiz,xenforo,yaf', 12 | 'Photo' => 'max:255', 13 | 'Title' => 'max:100', 14 | 'Location' => 'max:100', 15 | // 'About' => none, 16 | 'Email' => 'email|max:200', 17 | 'ShowEmail' => 'boolean', 18 | 'Gender' => 'in:u,m,f', 19 | 'CountVisits' => 'integer|min:0', 20 | 'CountInvitations' => 'integer|min:0', 21 | 'CountNotifications' => 'integer|min:0', 22 | 'InviteUserID' => 'exists:GDN_User,UserID', 23 | // 'DiscoveryText' => none, 24 | // 'Preferences' => none, 25 | // 'Permissions' => none, 26 | // 'Attributes' => none, 27 | 'DateSetInvitations' => 'date', 28 | 'DateOfBirth' => 'date', 29 | 'DateFirstVisit' => 'date', 30 | 'DateLastActive' => 'date', 31 | 'LastIPAddress' => 'ip|max:15', 32 | 'AllIPAddresses' => 'max:100', 33 | 'HourOffset' => 'integer', 34 | 'Score' => 'numeric', 35 | 'Admin' => 'boolean', 36 | 'Confirmed' => 'boolean', 37 | 'Verified' => 'boolean', 38 | 'Banned' => 'boolean', 39 | 'Deleted' => 'boolean', 40 | 'Points' => 'integer|min:0', 41 | 'CountUnreadConversations' => 'integer|min:0', 42 | 'CountDiscussions' => 'integer|min:0', 43 | 'CountUnreadDiscussions' => 'integer|min:0', 44 | 'CountComments' => 'integer|min:0', 45 | 'CountDrafts' => 'integer|min:0', 46 | 'CountBookmarks' => 'integer|min:0', 47 | ]; 48 | 49 | // auditing 50 | use AuditingTrait; 51 | public function getAuditors() 52 | { 53 | return [ 54 | 'DateInserted', 'InsertIPAddress', 55 | 'DateUpdated', 'UpdateIPAddress', 56 | ]; 57 | } 58 | 59 | // definitions 60 | protected $table = 'GDN_User'; 61 | protected $primaryKey = 'UserID'; 62 | 63 | protected $hidden = [ 'Password' ]; 64 | 65 | public function getDates() 66 | { 67 | return [ 68 | 'DateSetInvitations', 'DateOfBirth', 'DateFirstVisit', 69 | 'DateLastActive', 'DateInserted', 'DateUpdated' 70 | ]; 71 | } 72 | 73 | // relationships 74 | public function roles() 75 | { 76 | return $this->belongsToMany( 77 | '\BishopB\Forum\Role', 'GDN_UserRole', 'UserID', 'RoleID' 78 | ); 79 | } 80 | 81 | // custom 82 | /** 83 | * Encrypt a password that's compatible with the Vanilla world. 84 | */ 85 | public static function crypt_password($password, $method = 'vanilla') 86 | { 87 | return \Hash::make($password); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/views/themes/default/views/modules/discussionfilter.php: -------------------------------------------------------------------------------- 1 | Category, '') : ''; 6 | if ($Title == '') 7 | $Title = T('All Discussions'); 8 | 9 | $Bookmarked = T('My Bookmarks'); 10 | $MyDiscussions = T('My Discussions'); 11 | $MyDrafts = T('My Drafts'); 12 | $CountBookmarks = 0; 13 | $CountDiscussions = 0; 14 | $CountDrafts = 0; 15 | 16 | if ($Session->IsValid()) { 17 | $CountBookmarks = $Session->User->CountBookmarks; 18 | $CountDiscussions = $Session->User->CountDiscussions; 19 | $CountDrafts = $Session->User->CountDrafts; 20 | } 21 | 22 | if (!function_exists('FilterCountString')) { 23 | function FilterCountString($Count, $Url = '') { 24 | $Count = CountString($Count, $Url); 25 | return $Count != '' ? ''.$Count.'' : ''; 26 | } 27 | } 28 | if (C('Vanilla.Discussions.ShowCounts', TRUE)) { 29 | $Bookmarked .= FilterCountString($CountBookmarks, Url('/discussions/UserBookmarkCount')); 30 | $MyDiscussions .= FilterCountString($CountDiscussions); 31 | $MyDrafts .= FilterCountString($CountDrafts); 32 | } 33 | ?> 34 |
    35 | 67 |
    -------------------------------------------------------------------------------- /src/migrations/2014_09_23_194713_create_GDN_Permission_table.php: -------------------------------------------------------------------------------- 1 | integer('PermissionID', true); 18 | $table->integer('RoleID')->default(0)->index('FK_Permission_RoleID'); 19 | $table->string('JunctionTable', 100)->nullable(); 20 | $table->string('JunctionColumn', 100)->nullable(); 21 | $table->integer('JunctionID')->nullable(); 22 | // Vanilla may add these on the fly: 23 | // got to love dynamic schema! 24 | $table->boolean(DB::raw('`Garden.Email.View`'))->default(0); 25 | $table->boolean(DB::raw('`Garden.Settings.Manage`'))->default(0); 26 | $table->boolean(DB::raw('`Garden.Settings.View`'))->default(0); 27 | $table->boolean(DB::raw('`Garden.Messages.Manage`'))->default(0); 28 | $table->boolean(DB::raw('`Garden.SignIn.Allow`'))->default(0); 29 | $table->boolean(DB::raw('`Garden.Users.Add`'))->default(0); 30 | $table->boolean(DB::raw('`Garden.Users.Edit`'))->default(0); 31 | $table->boolean(DB::raw('`Garden.Users.Delete`'))->default(0); 32 | $table->boolean(DB::raw('`Garden.Users.Approve`'))->default(0); 33 | $table->boolean(DB::raw('`Garden.Activity.Delete`'))->default(0); 34 | $table->boolean(DB::raw('`Garden.Activity.View`'))->default(0); 35 | $table->boolean(DB::raw('`Garden.Profiles.View`'))->default(0); 36 | $table->boolean(DB::raw('`Garden.Profiles.Edit`'))->default(0); 37 | $table->boolean(DB::raw('`Garden.Curation.Manage`'))->default(0); 38 | $table->boolean(DB::raw('`Garden.Moderation.Manage`'))->default(0); 39 | $table->boolean(DB::raw('`Garden.PersonalInfo.View`'))->default(0); 40 | $table->boolean(DB::raw('`Garden.AdvancedNotifications.Allow`'))->default(0); 41 | $table->boolean(DB::raw('`Conversations.Moderation.Manage`'))->default(0); 42 | $table->boolean(DB::raw('`Conversations.Conversations.Add`'))->default(0); 43 | $table->boolean(DB::raw('`Vanilla.Approval.Require`'))->default(0); 44 | $table->boolean(DB::raw('`Vanilla.Comments.Me`'))->default(0); 45 | $table->boolean(DB::raw('`Vanilla.Discussions.View`'))->default(0); 46 | $table->boolean(DB::raw('`Vanilla.Discussions.Add`'))->default(0); 47 | $table->boolean(DB::raw('`Vanilla.Discussions.Edit`'))->default(0); 48 | $table->boolean(DB::raw('`Vanilla.Discussions.Announce`'))->default(0); 49 | $table->boolean(DB::raw('`Vanilla.Discussions.Sink`'))->default(0); 50 | $table->boolean(DB::raw('`Vanilla.Discussions.Close`'))->default(0); 51 | $table->boolean(DB::raw('`Vanilla.Discussions.Delete`'))->default(0); 52 | $table->boolean(DB::raw('`Vanilla.Comments.Add`'))->default(0); 53 | $table->boolean(DB::raw('`Vanilla.Comments.Edit`'))->default(0); 54 | $table->boolean(DB::raw('`Vanilla.Comments.Delete`'))->default(0); 55 | }); 56 | } 57 | 58 | 59 | /** 60 | * Reverse the migrations. 61 | * 62 | * @return void 63 | */ 64 | public function down() 65 | { 66 | Schema::drop('GDN_Permission'); 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /src/views/themes/default/views/post/discussion.php: -------------------------------------------------------------------------------- 1 | Data('_CancelUrl'); 5 | if (!$CancelUrl) { 6 | $CancelUrl = '/vanilla/discussions'; 7 | if (C('Vanilla.Categories.Use') && is_object($this->Category)) 8 | $CancelUrl = '/vanilla/categories/'.urlencode($this->Category->UrlCode); 9 | } 10 | 11 | ?> 12 |
    13 | DeliveryType() == DELIVERY_TYPE_ALL) 15 | echo Wrap($this->Data('Title'), 'h1', array('class' => 'H')); 16 | 17 | echo '
    '; 18 | echo $this->Form->Open(); 19 | echo $this->Form->Errors(); 20 | $this->FireEvent('BeforeFormInputs'); 21 | 22 | if ($this->ShowCategorySelector === TRUE) { 23 | echo '
    '; 24 | echo '
    '; 25 | echo $this->Form->Label('Category', 'CategoryID'), ' '; 26 | echo $this->Form->CategoryDropDown('CategoryID', array('Value' => GetValue('CategoryID', $this->Category))); 27 | echo '
    '; 28 | echo '
    '; 29 | } 30 | 31 | echo '
    '; 32 | echo $this->Form->Label('Discussion Title', 'Name'); 33 | echo Wrap($this->Form->TextBox('Name', array('maxlength' => 100, 'class' => 'InputBox BigInput')), 'div', array('class' => 'TextBoxWrapper')); 34 | echo '
    '; 35 | 36 | $this->FireEvent('BeforeBodyInput'); 37 | echo '
    '; 38 | echo $this->Form->BodyBox('Body', array('Table' => 'Discussion')); 39 | 40 | // echo Wrap($this->Form->TextBox('Body', array('MultiLine' => TRUE, 'format' => $this->Data('Discussion.Format'))), 'div', array('class' => 'TextBoxWrapper')); 41 | echo '
    '; 42 | 43 | $Options = ''; 44 | // If the user has any of the following permissions (regardless of junction), show the options 45 | // Note: I need to validate that they have permission in the specified category on the back-end 46 | // TODO: hide these boxes depending on which category is selected in the dropdown above. 47 | if ($Session->CheckPermission('Vanilla.Discussions.Announce')) { 48 | $Options .= '
  • '.CheckOrRadio('Announce', 'Announce', $this->Data('_AnnounceOptions')).'
  • '; 49 | } 50 | 51 | // if ($Session->CheckPermission('Vanilla.Discussions.Close')) 52 | // $Options .= '
  • '.$this->Form->CheckBox('Closed', T('Close'), array('value' => '1')).'
  • '; 53 | 54 | $this->EventArguments['Options'] = &$Options; 55 | $this->FireEvent('DiscussionFormOptions'); 56 | 57 | if ($Options != '') { 58 | echo '
    '; 59 | echo '
      ' . $Options .'
    '; 60 | echo '
    '; 61 | } 62 | 63 | $this->FireEvent('AfterDiscussionFormOptions'); 64 | 65 | echo '
    '; 66 | $this->FireEvent('BeforeFormButtons'); 67 | echo $this->Form->Button((property_exists($this, 'Discussion')) ? 'Save' : 'Post Discussion', array('class' => 'Button Primary DiscussionButton')); 68 | if (!property_exists($this, 'Discussion') || !is_object($this->Discussion) || (property_exists($this, 'Draft') && is_object($this->Draft))) { 69 | echo $this->Form->Button('Save Draft', array('class' => 'Button DraftButton')); 70 | } 71 | echo $this->Form->Button('Preview', array('class' => 'Button PreviewButton')); 72 | $this->FireEvent('AfterFormButtons'); 73 | echo Anchor(T('Cancel'), $CancelUrl, 'Button Cancel'); 74 | echo '
    '; 75 | 76 | 77 | 78 | echo $this->Form->Close(); 79 | echo '
    '; 80 | ?> 81 |
    82 | -------------------------------------------------------------------------------- /src/services/VanillaRunner.php: -------------------------------------------------------------------------------- 1 | user = $user; 18 | } 19 | 20 | /** 21 | * Emulate a call to index.php?p=$vanilla_module_path 22 | * Much of this ripped out of Vanilla's index.php 23 | */ 24 | public function view($segments) 25 | { 26 | // if a static asset, return it outright 27 | $asset = $this->is_static_asset($segments); 28 | if ($asset) { 29 | return \Response:: 30 | make(\File::get($asset))-> 31 | header('Content-Type', $this->get_content_type($asset)) 32 | ; 33 | } 34 | 35 | // otherwise, dispatch into vanilla 36 | $user = $this->user; 37 | 38 | $bootstrap = new VanillaBootstrap(); 39 | $bootstrap->call(function () use ($user, $segments) { 40 | // Create the session and stuff the user in 41 | \Gdn::Authenticator()->SetIdentity($user->getKey(), false /* no persist */); 42 | \Gdn::Session()->Start(false /* use set identity */, false /* no persist */); 43 | \Gdn::Session()->SetPreference('Authenticator', 'Gdn_Authenticator'); 44 | 45 | // Create and configure the dispatcher. 46 | $Dispatcher = \Gdn::Dispatcher(); 47 | 48 | $EnabledApplications = \Gdn::ApplicationManager()->EnabledApplicationFolders(); 49 | $Dispatcher->EnabledApplicationFolders($EnabledApplications); 50 | $Dispatcher->PassProperty('EnabledApplications', $EnabledApplications); 51 | 52 | // Process the request. 53 | $Dispatcher->Start(); 54 | $Dispatcher->Dispatch(implode('/', $segments)); 55 | }); 56 | } 57 | 58 | /** 59 | * Determine if these segments refer to a static, on disk asset and, 60 | * if so, return the path to it. 61 | * 62 | * @param array $segments 63 | * @return mixed 64 | */ 65 | protected function is_static_asset(array $segments) 66 | { 67 | // enumerate the possible targets 68 | $implode = '/'. implode('/', $segments); 69 | $targets = [ 70 | // a theme file published to the app? 71 | app_path() . '/views/packages/bishopb/laravel-forums' . $implode, 72 | 73 | // a theme file in this package? 74 | dirname(__DIR__) . '/views' . $implode, 75 | 76 | // a Vanilla resource? 77 | $this->get_vanilla_path() . $implode, 78 | 79 | // an upload? 80 | dirname(\Config::get('forum::paths.uploads')) . $implode, 81 | ]; 82 | 83 | foreach ($targets as $target) { 84 | if (is_readable($target)) { 85 | return $target; 86 | } 87 | } 88 | } 89 | 90 | /** 91 | * Get the content type of the target. 92 | * TODO: Replace this with a dead simple library 93 | * TODO: googling "github php mimetype to file extension returns heavy projects 94 | * @see http://stackoverflow.com/questions/19681854 95 | */ 96 | protected function get_content_type($target) 97 | { 98 | switch (pathinfo($target, PATHINFO_EXTENSION)) { 99 | case 'js' : return 'text/javascript'; 100 | case 'css': return 'text/css'; 101 | case 'png': return 'image/png'; 102 | case 'jpg': return 'image/jpg'; 103 | case 'gif': return 'image/gif'; 104 | default: return 'text/plain'; 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/views/themes/default/views/discussion/discussion.php: -------------------------------------------------------------------------------- 1 | Data('Discussion'); 13 | $Author = Gdn::UserModel()->GetID($Discussion->InsertUserID); // UserBuilder($Discussion, 'Insert'); 14 | 15 | // Prep event args. 16 | $CssClass = CssClass($Discussion, FALSE); 17 | $this->EventArguments['Discussion'] = &$Discussion; 18 | $this->EventArguments['Author'] = &$Author; 19 | $this->EventArguments['CssClass'] = &$CssClass; 20 | 21 | // DEPRECATED ARGUMENTS (as of 2.1) 22 | $this->EventArguments['Object'] = &$Discussion; 23 | $this->EventArguments['Type'] = 'Discussion'; 24 | 25 | // Discussion template event 26 | $this->FireEvent('BeforeDiscussionDisplay'); 27 | ?> 28 |
    29 |
    30 |
    31 |
    32 | 33 | 43 | 44 | 45 | 'MItem AuthorTitle')); 47 | echo WrapIf(htmlspecialchars(GetValue('Location', $Author)), 'span', array('class' => 'MItem AuthorLocation')); 48 | $this->FireEvent('AuthorInfo'); 49 | ?> 50 | 51 |
    52 |
    53 | 54 | DateInserted, 'html'), $Discussion->Url, 'Permalink', array('rel' => 'nofollow')); 56 | ?> 57 | 58 | ', '')); 60 | ?> 61 | 'MItem MItem-Source')).' '; 65 | 66 | // Category 67 | if (C('Vanilla.Categories.Use')) { 68 | echo ' '; 69 | echo ' '.T('in').' '; 70 | echo Anchor(htmlspecialchars($this->Data('Discussion.Category')), CategoryUrl($this->Data('Discussion.CategoryUrlCode'))); 71 | echo ' '; 72 | } 73 | $this->FireEvent('DiscussionInfo'); 74 | $this->FireEvent('AfterDiscussionMeta'); // DEPRECATED 75 | ?> 76 |
    77 |
    78 | FireEvent('BeforeDiscussionBody'); ?> 79 |
    80 |
    81 |
    82 | 85 |
    86 | FireEvent('AfterDiscussionBody'); 88 | WriteReactions($Discussion); 89 | if (GetValue('Attachments', $Discussion)) { 90 | WriteAttachments($Discussion->Attachments); 91 | } 92 | ?> 93 |
    94 |
    95 |
    96 |
    97 | -------------------------------------------------------------------------------- /src/views/themes/default/views/settings/addcategory.php: -------------------------------------------------------------------------------- 1 | Form->Open(); 4 | echo $this->Form->Errors(); 5 | ?> 6 |

    7 | 106 | Form->Close('Save'); ?> -------------------------------------------------------------------------------- /src/views/themes/default/views/settings/editcategory.php: -------------------------------------------------------------------------------- 1 | Form->Open(array('enctype' => 'multipart/form-data')); 4 | echo $this->Form->Errors(); 5 | ?> 6 |

    7 | 107 | Form->Close('Save'); ?> -------------------------------------------------------------------------------- /src/views/themes/default/views/modules/helper_functions.php: -------------------------------------------------------------------------------- 1 | 5 |
  • DiscussionID}"; ?>" class=""> 6 | 7 | 11 | 12 |
    Name, FALSE), DiscussionUrl($Discussion).($Discussion->CountCommentWatch > 0 ? '#Item_'.$Discussion->CountCommentWatch : ''), 'DiscussionLink'); 14 | ?>
    15 |
    16 | UserID = $Discussion->LastUserID; 19 | $Last->Name = $Discussion->LastName; 20 | 21 | echo NewComments($Discussion); 22 | 23 | echo ''.Gdn_Format::Date($Discussion->LastDate, 'html').UserAnchor($Last).''; 24 | ?> 25 |
    26 |
  • 27 | EventArgs['Content'] = $Content; 54 | $Sender->EventArgs['ContentUrl'] = $ContentURL; 55 | ?> 56 |
    " class=""> 57 |
    58 | 59 | FireEvent('AuthorPhoto'); 68 | ?> 69 | 70 | 71 | 'MItem AuthorTitle')); 73 | echo ' '.WrapIf(htmlspecialchars(GetValue('Location', $Author)), 'span', array('class' => 'MItem AuthorLocation')); 74 | $Sender->FireEvent('AuthorInfo'); 75 | ?> 76 | 77 |
    78 |
    79 | 80 | 'nofollow')); ?> 81 | 82 | 'MItem Source')); 86 | 87 | $Sender->FireEvent('ContentInfo'); 88 | ?> 89 |
    90 |
    TitleLimit), FALSE), $ContentURL, 'DiscussionLink'); ?>
    91 |
    92 | BodyLimit), $Content['Format'])), $ContentURL, 'BodyLink'); 94 | $Sender->FireEvent('AfterBody'); // seperate event to account for less space. 95 | ?> 96 |
    97 |
    98 | run();'; 22 | } 23 | 24 | /** 25 | * Run the adapter. We expect to do this on every request. 26 | */ 27 | public function run() 28 | { 29 | $this->adapt_db(); 30 | $this->adapt_request(); 31 | $this->adapt_pluginmanager(); 32 | $this->adapt_smarty(); 33 | $this->adapt_config(); 34 | } 35 | 36 | /** 37 | * Adapt Vanilla configuration to our current database. 38 | */ 39 | public function adapt_db() 40 | { 41 | $connection = \DB::connection(); 42 | if (! $connection instanceof \Illuminate\Database\MySqlConnection) { 43 | throw new VanillaForumsRequiresMysqlException( 44 | trans('Cannot use Vanilla with ') . get_class($connection) 45 | ); 46 | } 47 | 48 | foreach ($this->get_database_settings() as $key => $value) { 49 | $this->set($key, $value); 50 | } 51 | 52 | \Gdn::FactoryInstall( 53 | \Gdn::AliasDatabase, '\BishopB\Forum\GardenDatabase', 54 | NULL, \Gdn::FactorySingleton, [ 'Database' ] 55 | ); 56 | } 57 | 58 | /** 59 | * Get the database configuration values as an array of Vanilla key => value. 60 | */ 61 | public function get_database_settings() 62 | { 63 | $settings = []; 64 | 65 | $c = \DB::connection(); 66 | $settings['Database.Host'] = $c->getConfig('host'); 67 | $settings['Database.Name'] = $c->getConfig('database'); 68 | $settings['Database.User'] = $c->getConfig('username'); 69 | $settings['Database.Password'] = $c->getConfig('password'); 70 | $settings['Database.CharacterEncoding'] = $c->getConfig('charset'); 71 | $settings['Database.DatabasePrefix'] = ( 72 | '' == $c->getConfig('prefix') ? 73 | 'GDN_' : 74 | ($c->getConfig('prefix') . '_GDN_') 75 | ); 76 | 77 | return $settings; 78 | } 79 | 80 | /** 81 | * Adapt Vanilla to our current domain 82 | */ 83 | public function adapt_request() 84 | { 85 | \Gdn::FactoryInstall( 86 | \Gdn::AliasRequest, '\BishopB\Forum\GardenRequest', 87 | NULL, \Gdn::FactoryRealSingleton, 'Create' 88 | ); 89 | } 90 | 91 | /** 92 | * Hook ourselves into Vanilla's event system. 93 | */ 94 | public function adapt_pluginmanager() 95 | { 96 | \Gdn::FactoryInstall( 97 | \Gdn::AliasPluginManager, '\BishopB\Forum\GardenPluginManager' 98 | ); 99 | } 100 | 101 | /** 102 | * Hook ourselves into Vanilla's Smarty. 103 | * PS: Smarty sux ;) 104 | */ 105 | public function adapt_smarty() 106 | { 107 | \Gdn::FactoryInstall('ViewHandler.tpl', '\BishopB\Forum\GardenSmarty'); 108 | } 109 | 110 | /** 111 | * Inject configuration values. 112 | */ 113 | public function adapt_config() 114 | { 115 | $map = [ 116 | 'forum::forum.title' => 'Garden.Title', 117 | 'forum::forum.default-controller' => 'Routes.DefaultController', 118 | 'mail.from.address' => 'Garden.Email.SupportAddress', 119 | 'mail.from.name' => 'Garden.Email.SupportName', 120 | ]; 121 | foreach ($map as $ours => $theirs) { 122 | if (\Config::get($ours, false)) { 123 | $this->set($theirs, \Config::get($ours)); 124 | } 125 | } 126 | } 127 | } 128 | --------------------------------------------------------------------------------