'Hashtag',
'Description' => 'Automaticlly creates Vanilla Tags from title or content #Hashtags.',
'Version' => '1.1.2.5',
'RequiredApplications' => array('Vanilla' => '2.5'),
'RequiredTheme' => FALSE,
'MobileFriendly' => TRUE,
'HasLocale' => TRUE,
'SettingsUrl' => '/settings//Hashtag',
'SettingsPermission' => 'Garden.Settings.Manage',
'RegisterPermissions' => array('Plugins.Hashtag.View','Plugins.Hashtag.Add'),
'Author' => "Roger Brahmson",
'Github' => "https://github.com/rbrahmson/VanillaPlugins/tree/master/Hashtag",
'Source' => "https://github.com/rbrahmson/VanillaPlugins/tree/master/Hashtag",
'License' => "GNU GPL3"
);
/////////////////////////////////////////
class HashtagPlugin extends Gdn_Plugin {
///////////////////////////////////////////////
// Set the CSS
public function assetModel_styleCss_handler($Sender) {
$Sender->addCssFile('hashtag.css', 'plugins/Hashtag');
}
///////////////////////////////////////////////
//Plugin Settings
public function settingsController_Hashtag_create ($Sender, $Args) {
$Sender->permission('Garden.Settings.Manage');
$Debug = false;
$Sender->addCssFile('hashtag.css', 'plugins/Hashtag');
$Sender->setData('Title', t('Settings for the Hashtag Plugin'));
//
$Plugininfo = Gdn::pluginManager()->getPluginInfo('Hashtag', Gdn_PluginManager::ACCESS_PLUGINNAME);
//var_dump ($Plugininfo);
$Msg = '
'.$Plugininfo["Name"] . ' Plugin (Version:' . $Plugininfo["Version"]. ') Settings
';
//
//Verify tags can be added
if (version_compare(APPLICATION_VERSION, '2.5', '>=')) {
$Taggingsetting = 'Tagging.Discussions.Enabled';
$Tagpermission = 'Vanilla.Tagging.Add';
$Turnonmsg = anchor("Click to activate tagging", '/settings/tagging', ' PopupWindow',
array('rel' => 'nofollow'));
$RandM = anchor("Roles and Permissions", '/dashboard/role', ' PopupWindow',
array('rel' => 'nofollow'));;
} else {
$Taggingsetting = 'EnabledPlugins.Tagging';
$Tagpermission = 'Plugins.Tagging.Add';
$Turnonmsg = anchor("Click to view the plugins list then activate the Tagging plugin", '/settings/plugins/all/Tagging', ' PopupWindow',
array('rel' => 'nofollow'));
$RandM = anchor("Roles and Permissions", '/dashboard/role', ' PopupWindow',
array('rel' => 'nofollow'));
}
if (!c($Taggingsetting)) {
$Msg .= 'Warning: Tagging is not enabled yet. The Hashtag plugin required that you turn on Tagging. '.
$Turnonmsg.'
';
}
$Msg .= 'General Note:'.
$Textstyle.'This plugin auto-creates tags from #Hashtags embedded in the discussion. This does not override the required Vanilla permissions.'.''.
$Textstyle.' For this plugin to work the following two permissions must be set in '.$RandM.':'.''.
$Textstyle.'
(1) '. $Tagpermission .' and (2) Plugins.Hashtag.Add'.'
';
//
$Sender->Title($Msg);
$Sender->setData('Title', $Msg);
//
$Sender->addSideMenu('dashboard/settings/plugins');
$this->SettingDefaults($Sender,'settingsController');
$Goterror =false;
$TopWarning = '';
$FieldErrors = '';
//
$ConfigurationModule = new ConfigurationModule($Sender);
$Validation = new Gdn_Validation();
$ConfigurationModel = new Gdn_ConfigurationModel($Validation);
$Sender->Form->SetModel($ConfigurationModel);
//
if ($Sender->Form->authenticatedPostBack()) {
$Saved = $Sender->Form->showErrors();
$Saved = $Sender->Form->Save();
$FormPostValues = $Sender->Form->formValues();
$Sender->Form->SetData($FormPostValues);
$Validation = new Gdn_Validation();
$Data = $Sender->Form->formValues();
// Flag to also check body for hashtags
$SearchBody = getvalue('Plugins.Hashtag.SearchBody',$Data);
// Flag to link hashtags
$EmbedLinks = getvalue('Plugins.Hashtag.EmbedLinks',$Data);
// Minimum number of letters in an #Hashtag
$Minletters = getvalue('Plugins.Hashtag.Minletters',$Data);
$FieldErrors = $this->CheckField($Sender,$Minletters,
Array('Integer'=>'?','Required'=> 'Integer','Min'=> 4,'Max'=>10),
'Minimum number of letters in a #hashtag','Plugins.Hashtag.Minletters');
// Maximum number of letters in an #Hashtag
$Maxletters = getvalue('Plugins.Hashtag.Maxletters',$Data);
if ($FieldErrors == '') $FieldErrors = $this->CheckField($Sender,$Maxletters,
Array('Integer'=>'?','Required'=> 'Integer','Min'=> 4,'Max'=>140),
'Maximum number of letters in a #hashtag','Plugins.Hashtag.Maxletters');
if ($FieldErrors == '') {
if ($Minletters >= $Maxletters) {
$FieldErrors = wrap('Maximum number of letters should be bigger than the minimum number of letters.',
'span class=SettingError');
$addError = $Sender->Form->addError($FieldErrors,'Plugins.Hashtag.Maxletters');
}
}
// Validate flags
if ($FieldErrors == '' && $EmbedLinks) {
if (!$SearchBody) {
$FieldErrors = wrap('You turned on "Link Embedded #Hashtags" which required the "Check Body for #Hashtags" Option.',
'span class=SettingWarning');
$addError = $Sender->Form->addError($FieldErrors,'Plugins.Hashtag.EmbedLinks');
} elseif (c('Garden.Format.Hashtags')) {
$FieldErrors = wrap('You turned on "Link Embedded #Hashtags". This will be ignored until you turn off "Garden.Format.Hashtags" in config.php.',
'span class=SettingWarning');
$addError = $Sender->Form->addError($FieldErrors,'Plugins.Hashtag.EmbedLinks');
}
}
//
if ($FieldErrors != '') {
$Goterror=true;
$Sender=$Validation->addValidationResult('Plugins.Hashtag.SearchBody', ' ');
$TopWarning = t('Errors need to be corrected. Incomplete settings saved');
Gdn::controller()->informMessage($TopWarning);//,'DoNotDismiss');
}
if (!$Validation->validate($FormPostValues)) $Goterror=true;
if ($Goterror) {
$Sender=$Validation->addValidationResult('Plugins.Hashtag.SearchBody', ' ');
SaveToConfig('Plugins.Hashtag.IncompleteSetup',TRUE);
} else {
SaveToConfig('Plugins.Hashtag.IncompleteSetup',FALSE);
}
// NOT POSTBACK
} else {
if (c('Plugins.Hashtag.IncompleteSetup'))
$TopWarning = 'Previously saved settings are incomplete/invalid. Review and save correct values.';
$Sender->Form->SetData($ConfigurationModel->Data);
}
//
$PluginConfig = $this->SetConfig($Sender,Array('TopWarning' => $TopWarning),$Debug);
$ConfigurationModule->initialize($PluginConfig);
$ConfigurationModule->renderAll();
}
/////////////////////////////////////////
public function SettingDefaults($Sender,$CallType = '') {
//Set default confi options
$Debug = false;
$Minletters = c('Plugins.Hashtag.Minletters',4);
SaveToConfig('Plugins.Hashtag.Minletters',$Minletters);
$Maxletters = c('Plugins.Hashtag.Maxletters',140);
SaveToConfig('Plugins.Hashtag.Maxletters',$Maxletters);
$SearchBody = c('Plugins.Hashtag.SearchBody',false);
SaveToConfig('Plugins.Hashtag.SearchBody',$SearchBody);
$EmbedLinks = c('Plugins.Hashtag.EmbedLinks',false);
SaveToConfig('Plugins.Hashtag.EmbedLinks',$EmbedLinks);
}
/////////////////////////////////////////
// Set Confogiration Array
public function SetConfig($Sender,$Errors = Array(),$Debug) {
$Separator = ' ';
$Headstyle = '#  ';
$Subhstyle = '';
$Textstyle = '';
$Warnstyle = '';
$Errorstyle = '';
$Squeeze = ' ';
$Notestyle = '';
$Topmessage = '';
if (trim($Errors['TopWarning'])) $Topmessage .= $Warnstyle.$Errors['TopWarning'].'';
$WarnGarden = '';
if (c('Garden.Format.Hashtags')) $WarnGarden = ''.t('Right now it is not set to false.').'';
//Verify tags can be added
if (version_compare(APPLICATION_VERSION, '2.5', '>=')) {
$Taggingsetting = 'Tagging.Discussions.Enabled';
$Tagpermission = 'Vanilla.Tagging.Add';
$Turnonmsg = anchor("Click to activate tagging", '/settings/tagging', ' PopupWindow',
array('rel' => 'nofollow'));;
} else {
$Taggingsetting = 'EnabledPlugins.Tagging';
$Tagpermission = 'Plugins.Tagging.Add';
$Turnonmsg = anchor("Click to view the plugins list then activate the Tagging plugin", '/settings/plugins/all/Tagging', ' PopupWindow',
array('rel' => 'nofollow'));;
}
$Notactivemsg = '';
if (!c($Taggingsetting)) {
$Notactivemsg = 'Note: Tagging is not enabled yet. The Hashtag plugin required that you turn on Tagging.
'.
$Turnonmsg.'
';
}
//
$PluginConfig = array(
/*- Option to search body for #Hashtags-*/
'Plugins.Hashtag.SearchBody' => array(
'Control' => 'CheckBox',
'Description' => $Topmessage.
$Notactivemsg.
$Headstyle.'Check Body for #Hashtags'.'',
'LabelCode' => $Textstyle.'Search the discussion and comment bodies for #Hashtags (otherwise only the discussion title is scanned)'.$Squeeze,
'Default' => TRUE),
/*- Option to turn off "" in the body (so it won't do search on hashtags (because they might be searchable as tags if autohshtag is enabled on the body)-*/
'Plugins.Hashtag.EmbedLinks' => array(
'Control' => 'CheckBox',
'Description' => wrap('Link Embedded #Hashtags
','span class=SettingHead').
$Textstyle.'Note: Three conditions must exist for this feature to be active:'.
'
(1) The "Check Body for #Hashtags" above must be checked.'.'
'.
$Textstyle.' (2) "Garden.Format.Hashtags" must be set to "false" in config.php. '.$WarnGarden.'
'.
$Textstyle.' (3) Plugins.Hashtag.View must be set in Roles and Permissions'.'
',
'LabelCode' => $Textstyle.'Set the embedded #hashtags to link to other discussions tagged with the same hashtags.'.$Squeeze,
'Default' => TRUE),
/*- Minimum number of letters in a #word to be considered a Hashtag-*/
'Plugins.Hashtag.Minletters' => array(
'Control' => 'textbox',
'Description' => $Textstyle.'Minimum number of letters in a #word to be considered a Hashtag:'.$Errors['Minletters'],
'LabelCode' => $Headstyle.'Hashtag Sizing:',
'Default' => 4),
/*- Maximum number of letters in a #word to be considered a Hashtag-*/
'Plugins.Hashtag.Maxletters' => array(
'Control' => 'textbox',
'Description' => $Textstyle.'Maximum number of letters in a #word to be considered a Hashtag:'.$Errors['Maxletters'],
'LabelCode' => '' ,
'Default' => 140),
);
return $PluginConfig;
}
/////////////////////////////////////////
// Check Configuration Settings
public function CheckSettings($Sender,$Type='All',$Debug) {
if ($Debug) echo "
".__FUNCTION__.' '.__LINE__.' Called by: ' . debug_backtrace()[1]['function'];
//
$Warn = '';
$Error = '';
//Get the menu filled variables
$Data = $Sender->Form->formValues();
$SearchBody = getvalue('Plugins.Hashtag.SearchBody',$Data);
$EmbedLinks = getvalue('Plugins.Hashtag.EmbedLinks',$Data);
$Minletters = getvalue('Plugins.Hashtag.Minletters',$Data);
$Maxletters = getvalue('Plugins.Hashtag.Maxletters',$Data);
//
if ($Type == 'All' || $Type == 'Errors') {
//if ($Debug) echo '
'.__LINE__.'Backward:'.$Backward;
if ($Minletters == '') $Minletters = 4;
if (!is_numeric($Minletters) || $Minletters < 4 || $Minletters > 10) {
if (!is_numeric($Minletters)) {
$Error = $Error .'
Invalid minimum number of #Hashtag letters: "'.$Minletters.'" is not numeric';
} else {
$Error = $Error .'
Invalid minimum number of #Hashtag letters:"'.$Minletters.'". Should be between 4 and 10.';
}
}
//
if ($Maxletters == '') $Maxletters = 4;
if (!is_numeric($Maxletters) || $Maxletters < 4 || $Maxletters > 140) {
if (!is_numeric($Maxletters)) {
$Error = $Error .'
Invalid Maximum number of #Hashtag letters: "'.$Maxletters.'" is not numeric';
} else {
$Error = $Error .'
Invalid Maximum number of #Hashtag letters:"'.$Maxletters.'". Should be between 4 and 10.';
}
}
//
if (!($Maxletters > $Minletters)) {
$Error = $Error .'
Maximum number of letters should be larger than the Minimum number of letters';
}
//
}
if ($Type == 'All' || $Type == 'Warnings') {
if ($EmbedLinks && c('Garden.Format.Hashtags')) {
$Warn = $Warn .'
You turned on "Link Embedded #Hashtags". This will be ignored until you turn off "Garden.Format.Hashtags" in config.php';
}
if ($EmbedLinks && !$SearchBody) {
$Warn = $Warn .'
You turned on "Link Embedded #Hashtags" which required the "Check Body for #Hashtags" Option. ';
}
}
if ($Type != 'All' && $Type != 'Warnings' && $Type != 'Errors') {
return 'Error - Parameter '.$Type.' Unaccepted by '.__FUNCTION__;
}
//
//*****************************************//
if ($Error) {
$Error = substr($Error,4);
//$Error = Wrap(substr($Error,4),'span class=SettingError');
}
if ($Warn) {
$Warn = substr($Warn,4);
$Warn = Wrap(substr($Warn,4),'span class=SettingWarning');
}
if ($Debug)
echo wrap('...'.__LINE__.' Error:'.$Error.' Warn:'.$Warn,'p class=SettingWarning');
$Result = $Error.$Warn;
return $Result;
}
/////////////////////////////////////////
// Check speicific field, return error message
public function CheckField($Sender,$Field=FALSE,$Checks=Array('Required'),$Title = 'Field', $Fieldname = '', $Style = 'span class=SettingError', $Debug = false) {
$Errormsg='';
foreach ($Checks as $Test => $Value) {
//echo '
'.__line__.$Errormsg;
if ($Errormsg == '') {
//echo '
'.__LINE__.'Test:'.$Test.' Value:'.$Value.' on:'.$Field;
if($Test == 'Required') {
if ($Field == '') {
$Errormsg='is required';
} else {
if ($Value == 'Integer' && !ctype_digit($Field)) {
$Errormsg='must be an integer';
} elseif ($Value == 'Numeric' && !is_numeric($Field)) {
$Errormsg='must be numeric';
} elseif ($Value == 'Alpha' && preg_match("/[0-9]+/", $Field)) {
$Errormsg='must be alphabetic';
}
}
} elseif (($Test == 'Integer' | $Test == 'Min' | $Test == 'Max') && !ctype_digit($Field)) {
$Errormsg='must be an integer';
} elseif (($Test == 'Numeric' | $Test == 'Min' | $Test == 'Max') && !is_numeric($Field)) {
$Errormsg='must be numeric';
} elseif ($Test == 'Alpha' && preg_match("/[0-9]+/", $Field)) {
$Errormsg='must be alphabetic';
} elseif ($Test == 'Min') {
if ($Field < $Value) $Errormsg='must not be less than '.$Value;
} elseif ($Test == 'Max') {
if ($Field > $Value) $Errormsg='must not be greater than '.$Value;
}
}
}
//echo '
'.__line__.$Errormsg;
if ($Errormsg != '') {
$Errormsg = wrap(t($Title).' '.t($Errormsg),$Style);
if ($Fieldname != '') $addError = $Sender->Form->addError($Errormsg, $Fieldname);
}
//echo '
'.__line__.$Errormsg;
return $Errormsg;
}
//////////////////////////////////////
//Handle auto-linking #hashtags embedded in the body
public function DiscussionController_AfterCommentFormat_Handler($Sender) {
$Debug = false;
if ($Debug) {
$Msg = __FUNCTION__.' '.__LINE__.' Called by: ' . debug_backtrace()[1]['function'];
Gdn::controller()->informMessage($Msg);
echo Wrap($Msg,'br');
}
// Do this only if Vanilla doesn't format hashtgs and the admin asked for this option
if (c('Garden.Format.Hashtags')) return;
if (!c('Plugins.Hashtag.EmbedLinks')) return;
if (!c('Plugins.Hashtag.SearchBody')) return;
if (!Gdn::session()->checkPermission('Plugins.Hashtag.View')) return; //This requires View Hashtags permission
//
$Object = $Sender->EventArguments['Object'];
$FormatBody = $Object->FormatBody;
$CommentID = getValueR('CommentID',$Object);
$DiscussionID = getValueR('DiscussionID',$Object);
$Name = '';
//
if ($Debug) {
$this->Showdata($DiscussionID,__LINE__.'---DiscussionID---','',0,' ',true);
$this->Showdata($CommentID,__LINE__.'---CommentID---','',0,' ',true);
$this->Showdata($Name,__LINE__.'---Name---','',0,' ',true);
$this->Showdata($Object->FormatBody,__LINE__.'---$Object->FormatBody---','',0,' ',true);
$this->Showdata($Object,__LINE__.'---Object---','',0,' ',true);
}
//
// Handle #hashtag embedded in the body
// creating links like: /discussions/tagged/hashtag
$Mixed = Gdn_Format::replaceButProtectCodeBlocks(
'/(^|[\s,\.>])\#([\w\-]+)(?=[\s,\.!?<]|$)/i',
'\1'.anchor('#\2', '/discussions/tagged/\2 ').'\3',
$FormatBody);
if ($Debug) $this->Showdata($Mixed,__LINE__.'---Mixed---','',0,' ',true);
$Sender->EventArguments['Object']->FormatBody = $Mixed;
}
/////////////////////////////////////
public function GetCurrentTags($Sender,$Discussion,$Debug = false) {
if ($Debug) {
$Msg = __FUNCTION__.' '.__LINE__.' Called by: ' . debug_backtrace()[1]['function'].debug_backtrace()[0]['line'].' ---> '. debug_backtrace()[0]['function'];
Gdn::controller()->informMessage($Msg);
echo Wrap($Msg,'br');
}
//
$DiscussionID = $Discussion->DiscussionID;
$Sqlfields = 't.TagID, t.Name, t.FullName, td.DiscussionID, td.TagID';
if ($Debug) {
$Sqlfields = 't.TagID, t.Name, t.FullName, t.CountDiscussions, t.Dateinserted tDateinserted, td.Dateinserted tdDateinserted, td.DiscussionID, td.TagID';
//$this->Showdata($Discussion,__LINE__.'---Discussion---','',0,' ',true);
//decho($Discussion);
$this->Showdata($DiscussionID,__LINE__.'---DiscussionID---','',0,' ',true);
$this->Showdata($Discussion->Name,__LINE__.'---Name---','',0,' ',true);
$this->Showdata($Discussion->Body,__LINE__.'---Body---','',0,' ',true);
}
//
$TagSql = clone Gdn::sql(); //Don't interfere with any other sql process
$TagSql->Reset(); //Clean slate
$Taglist = $TagSql //Get expanded tag info for this discussion
->select($Sqlfields)
->from('TagDiscussion td')
->join('Tag t', 't.TagID = td.TagID')
->where('td.discussionID', $DiscussionID)
->get()->resultArray();
if ($Debug) $this->Showdata($Taglist,__LINE__.'---Taglist---','',0,' ',true);
/*Sample Structure:
Taglist--- array
....(1) array(5):[0]: value: array
........(2) _integer:TagID value:"7"
........(2) string:Name value:"test"
........(2) string:FullName value:"#test"
........(2) _integer:CountDiscussions value:"2"
........(2) string:tDateinserted value:"2015-05-10 13:28:44"
........(2) string:tdDateinserted value:"2015-05-10 23:39:12"
........(2) _integer:DiscussionID value:"1627"
....(1) array(5):[1]: value: array
........(2) _integer:TagID value:"10"
........(2) string:Name value:"self"
........(2) string:FullName value:"#self"
........(2) _integer:CountDiscussions value:"1"
........(2) string:tDateinserted value:"2015-05-10 23:39:12"
........(2) string:tdDateinserted value:"2015-05-10 23:39:12"
........(2) _integer:DiscussionID value:"1627"
*/
//$Alltags = rtrim($Hashtags.','.$Tags,', ');
//if ($Debug) $this->Showdata($Alltags,__LINE__.'---Alltags---','',0,' ',true);
return $Taglist;
}
/////////////////////////////////////
public function GetHashTags($Sender,$Name,$Body,$Debug = false) {
if ($Debug) {
$Msg = __FUNCTION__.' '.__LINE__.' Called by: ' . debug_backtrace()[1]['function'].debug_backtrace()[0]['line'].' ---> '. debug_backtrace()[0]['function'];
Gdn::controller()->informMessage($Msg);
echo Wrap($Msg,'br');
}
//$Debug = true;
//Search for hashtags
$Body = str_replace(" "," ",$Name.' '.$Body." "); //These html spaces interfere with parsing blanks...
preg_match_all('/#([^\s]+)/',$Body, $Matches);
$Tagarray = $Matches[0];
//var_dump($Matches);
var_dump($Matches[0]);
$Minletters = c('Plugins.Hashtag.Minletters',4);
$Maxletters = c('Plugins.Hashtag.Maxletters',140);
$Pattern = '/^(?=.{'.$Minletters.','.$Maxletters.'}$)(#|\x{ff03}){1}([0-9_\p{L}]*[_\p{L}][0-9_\p{L}]*)$/u';
$unwantedChars = array(',', '.', "'", '"', '!', '?' ,' '); // create array with unwanted chars
$Hashtags = '';
foreach ($Tagarray as $Key => $Tag) {
if ($Debug) $this->Showdata($Tag,__LINE__.' Tag:','',0,' ',true);
if ($Debug) echo "
Key:".$Key."Tag:".$Tag.'
';
$Sanitized = trim(rtrim(strip_tags($Tag),',!?."'."'"));
$Sanitized = strtok(str_replace($unwantedChars, ' ', strtolower(strip_tags($Tag))).' ',' '); // remove unwanted chars and use lowecase
if (!preg_match($Pattern, $Sanitized)) {
if ($Debug) $this->Showdata($Sanitized,'Invalid hashtag:','',0,' ',true);
if ($Debug) echo '
Invalid hashtag:'.$Sanitized,'
';
unset($Tagarray[$Key]);
} else {
$Hashtags = $Sanitized .', '.$Hashtags;
//if ($Debug) $this->Showdata($Hashtags,__LINE__.' Hashtags:','',0,' ',true);
}
}
$Hashtags = rtrim($Hashtags,', ');
if ($Debug) $this->Showdata($Hashtags,__LINE__.' Hashtags:','',0,' ',true);
if ($Debug) die(0);
return $Hashtags;
}
///////////////////////////////////////
//This functionality is performed by the DiscussionController_AfterCommentFormat_Handler
public function xxxREDUNDANTxxxDiscussioncontroller_BeforeDiscussionDisplay_handler($Sender,$Args) {
// Optionally replace embedded hashtags with links to the tags.
$Debug = false;
$Args = $Sender->EventArguments;
if ($Debug) {
$Msg = __FUNCTION__.' '.__LINE__.' Called by: ' . debug_backtrace()[1]['function'].' ---> '. debug_backtrace()[0]['function'];
Gdn::controller()->informMessage($Msg);
echo Wrap($Msg,'br');
//$this->Showdata($Args,'---Args---','',0,' ',false);
}
// Do this only if Vanilla doesn't format hashtgs and the admin asked for this option
if (c('Garden.Format.Hashtags')) return;
if (!c('Plugins.Hashtag.EmbedLinks')) return;
if (!c('Plugins.Hashtag.SearchBody')) return;
if (!Gdn::session()->checkPermission('Plugins.Hashtag.View')) return; //This required View Hashtags permission
//
$DiscussionID = val('DiscussionID', $Args['Discussion'], 0);
$CommentID = val('CommentID', $Args['Discussion'], 0);
$Tags = val('Tags', $Args['Discussion'], '');
$Name = val('Name', $Args['Discussion'], '');
$Body = val('Body', $Args['Discussion'], '');
//
if ($Debug) {
$this->Showdata($DiscussionID,__LINE__.'---DiscussionID---','',0,' ',true);
$this->Showdata($CommentID,__LINE__.'---CommentID---','',0,' ',true);
$this->Showdata($Name,__LINE__.'---Name---','',0,' ',true);
$this->Showdata($Body,__LINE__.'---Body---','',0,' ',true);
//$this->Showdata($Tags,__LINE__.'---Tags---','',0,' ',true);
}
// Handle #hashtag embedded in the body
// creating links like: /discussions/tagged/hashtag
$Mixed = Gdn_Format::replaceButProtectCodeBlocks(
'/(^|[\s,\.>])\#([\w\-]+)(?=[\s,\.!?<]|$)/i',
'\1'.anchor('#\2', '/discussions/tagged/\2 ').'\3',
$Body
);
if ($Debug) $this->Showdata($Mixed,__LINE__.'---Mixed---','',0,' ',true);
$Sender->EventArguments['Discussion']->Body = $Mixed;
}
///////////////////////////////////////
//This hook handles the saving of comments (but not the initial discussion body).
public function PostController_AfterCommentSave_Handler($Sender, $Args) {
$Debug = false;
if ($Debug) {
$Msg = __FUNCTION__.' '.__LINE__.' Called by: ' . debug_backtrace()[1]['function'].' ---> '. debug_backtrace()[0]['function'];
Gdn::controller()->informMessage($Msg);
echo Wrap($Msg,'br');
}
//Verify tags can be added
if (version_compare(APPLICATION_VERSION, '2.5', '>=')) {
$Taggingsetting = 'Tagging.Discussions.Enabled';
$Tagpermission = 'Vanilla.Tagging.Add';
} else {
$Taggingsetting = 'EnabledPlugins.Tagging';
$Tagpermission = 'Plugins.Tagging.Add';
}
if (!Gdn::session()->checkPermission($Tagpermission)) return; //This required Add Tags permission
if (!Gdn::session()->checkPermission('Plugins.Hashtag.Add')) return; //This required Add Hashtags permission
if (!c($Taggingsetting)) return; //If t then we're done here
if (!c('Plugins.Hashtag.SearchBody')) return; //If not porcessing the body then we're done here
//
$Discussion = $Sender->EventArguments['Discussion'];
$Comment = $Sender->EventArguments['Comment'];
$Body = $Comment->Body;
//
//if ($Debug) {
//$this->Showdata($Discussion,__LINE__.'---Discussion---','',0,' ',true);
//decho($Discussion);
//$this->Showdata($Discussion->DiscussionID,__LINE__.'---DiscussionID---','',0,' ',true);
//$this->Showdata($Discussion->CategoryID,__LINE__.'---CategoryID---','',0,' ',true);
//$this->Showdata($Discussion->Name,__LINE__.'---Name---','',0,' ',true);
//$this->Showdata($Body,__LINE__.'---Body---','',0,' ',true);
//}
//Get the hashtags embedded in the comment.
$Hashtags = $this->GetHashTags($Sender,'',$Body,0,false,0,$Debug); //Get the content embedded hashtags
//if ($Debug) $this->Showdata($Hashtags,__LINE__.'---Hashtags---','',0,' ',true);
//
//if (trim($Hashtags) == '') return;
// Now add the hashtags to this discussion
$TagModel = new TagModel;
$Types = array();
TagModel::instance()->saveDiscussion($Discussion->DiscussionID, $Hashtags, $Types, $Discussion->CategoryID);
return;
//The following code is not executed. Turns out the Tag model ignored suplicate tags so we don't need
//to remove duplicated. I keep it here just in case something changes in the future...
//
// Check existing discussion tags
$Currenttags = $this->GetCurrentTags($Sender,$Discussion,0,$Debug);
//if ($Debug) $this->Showdata($Currenttags,__LINE__.'---Currenttags---','',0,' ',true);
// Go over the current tag list and check with hashtags needs to be added to this discussion
$Hashtagarray =array_map("trim", explode(',',$Hashtags));
//if ($Debug) $this->Showdata($Hashtagarray,__LINE__.'---Hashtagarray---','',0,' ',true);
// Scan the current tags for this discussion
foreach ($Currenttags as $Outerkey => $Outervalue) {
//echo '
'.__LINE__.' Outerkey:'.$Outerkey.' Outervalue:'.$Outervalue;
foreach ($Outervalue as $Key => $Value) {
if ($Key == 'FullName') {
$Entry = array_search(trim($Value), $Hashtagarray);
echo '
'.__LINE__.' Key:'.$Key.' Value:'.$Value.' Entry:'.$Entry;
if ($Entry !== false) unset($Hashtagarray[$Entry]);
}
}
}
if ($Debug) $this->Showdata($Hashtagarray,__LINE__.'---Hashtagarray---','',0,' ',true);
//
if (count($Hashtagarray) == 0) return;
echo '
'.__LINE__.' Number of tags to add:'.count($Hashtagarray);
// Now add the tags for the hashtags not already tagged in this discussion
$TagModel = new TagModel;
$FormTags = implode(',', $Hashtagarray);
$Types = array();
TagModel::instance()->saveDiscussion($Discussion->DiscussionID, $FormTags, $Types, $Discussion->CategoryID);
}
///////////////////////////////////////
//This hook handles the saving of the initial discussion body (but not comments).
public function TaggingPlugin_SaveDiscussion_handler($Sender,$Args) {
$Debug = false;
if ($Debug) {
$Msg = 'Saving Discussion... '. __FUNCTION__.' '.__LINE__.' Called by: ' . debug_backtrace()[1]['function'].' ---> '. debug_backtrace()[0]['function'];;
Gdn::controller()->informMessage($Msg);
echo Wrap($Msg,'br');
}
//Verify tags can be added
if (version_compare(APPLICATION_VERSION, '2.5', '>=')) {
$Taggingsetting = 'Tagging.Discussions.Enabled';
$Tagpermission = 'Vanilla.Tagging.Add';
} else {
$Taggingsetting = 'EnabledPlugins.Tagging';
$Tagpermission = 'Plugins.Tagging.Add';
}
if (!Gdn::session()->checkPermission($Tagpermission)) return; //This required Add Tags permission
if (!Gdn::session()->checkPermission('Plugins.Hashtag.Add')) return; //This required Add Hashtags permission
if (!c($Taggingsetting)) return; //If t then we're done here
if (!c('Plugins.Hashtag.SearchBody')) return; //If not porcessing the body then we're done here
//
$FormPostValues = val('Data', $Sender->EventArguments, array());
$Tags = val('Tags', $Sender->EventArguments,0);
$CategoryID = val('CategoryID', $Sender->EventArguments,0);
//
$DiscussionID = val('DiscussionID', $FormPostValues, 0);
$CommentID = val('CommentID', $FormPostValues, 0);
$Tags = val('Tags', $FormPostValues, '');
$Name = val('Name', $FormPostValues, '');
$Body = val('Body', $FormPostValues, '');
if ($Debug) {
//echo "
DiscussionID:".$DiscussionID.'
';
//echo "
CommentID:".$CommentID.'
';
//echo "
Name:".$Name.'
';
//echo "
Body:".$Body.'
';
//echo "
Tags:".$Tags.'
';
//decho ($FormPostValues);
$this->Showdata($DiscussionID,'---DiscussionID---','',0,' ',true);
$this->Showdata($CommentID,'---CommentID---','',0,' ',true);
$this->Showdata($Name,'---Name---','',0,' ',true);
$this->Showdata($Body,'---Body---','',0,' ',true);
$this->Showdata($Tags,'---Tags---','',0,' ',true);
$this->Showdata($FormPostValues,'---FormPostValues---','',0,' ',true);
//die(0);
}
$SearchBody = c('Plugins.Hashtag.SearchBody',FALSE);
if (!$SearchBody) { //Automatic Hashtags only set on the discussion title?
if ($CommentID) return; //Then if this is a comment there is nothing more to do
$Body = ''; //Don't look at the body
}
$Hashtags = $this->GetHashTags($Sender,$Name,$Body,$Debug); //Get the content embedded hashtags
if ($Debug) $this->Showdata($Hashtags,__LINE__.'---Hashtags---','',0,' ',true);
$Alltags = rtrim($Hashtags.','.$Tags,', ');
if ($Debug) $this->Showdata($Alltags,__LINE__.'---Alltags---','',0,' ',true);
$Sender->EventArguments['Tags'] = $Alltags; //and add them to the list of tags on the form
//die(0);
}
///////////////////////////////////////
// Display data for debugging
public function Showdata($Data, $Message, $Find, $Nest=0, $BR='
', $Echo = true) {
//var_dump($Data);
$Line = "
".str_repeat(".",$Nest*4)."(".($Nest).") ".$Message."";
if ($Echo) echo $Line;
else Gdn::controller()->informMessage($Line);
$Nest +=1;
if ($Nest > 20) {
echo wrap('****Nesting Truncated****','h1');
return;
}
if ($Message == 'DUMP') echo '
Type:'.gettype($Data).'
';//var_dump($Data);
if (is_object($Data) || is_array($Data)) {
echo ' '.gettype($Data).' ';
if (is_array($Data) && !count($Data)) echo '....Debug:'.$Data[0];
foreach ($Data as $key => $value) {
if (is_object($value)) {
$this->Showdata($value,' '.gettype($value).'('.count($value).'):'.$key.' value:','',$Nest,'');
} elseif (is_array($value)) {
$this->Showdata($value,' '.gettype($value).'('.count($value).'):['.$key.']: value:','',$Nest,'');
} elseif (is_bool($value)) {
$this->Showdata($value,' '.gettype($value).':'.$key.' value[]:','',$Nest,'');
} elseif (is_string($value)) {
$this->Showdata($value,' '.gettype($value).':'.$key.' value:','',$Nest,'');
} else {
$this->Showdata($value,'_'.gettype($value).':'.$key.' value:','',$Nest,'');
}
}
} else {
if ($Echo)
echo wrap('"'.$Data.'"','b');
else Gdn::controller()->informMessage($Data,'DoNotDismiss');
//var_dump($Data);
}
}
///////////////////////////////////////////////
}