additional_plugins/serendipity_event_metadesc/serendipity_event_metadesc.php
2021-07-12 15:44:23 +02:00

396 lines
21 KiB
PHP

<?php
if (IN_serendipity !== true) {
die ("Don't hack!");
}
@serendipity_plugin_api::load_language(dirname(__FILE__));
class serendipity_event_metadesc extends serendipity_event {
var $title = PLUGIN_METADESC_NAME;
var $save_title = '';
var $save_subtitle = '';
var $meta_title = '';
function introspect(&$propbag) {
global $serendipity;
$propbag->add('name', PLUGIN_METADESC_NAME);
$propbag->add('description', PLUGIN_METADESC_DESC);
$propbag->add('stackable', false);
$propbag->add('author', 'Garvin Hicking, Judebert, Don Chambers');
$propbag->add('version', '0.15.7');
$propbag->add('requirements', array(
'serendipity' => '0.8',
'php' => '4.1.0'
));
$propbag->add('event_hooks', array(
'genpage' => true,
'frontend_header' => true,
'backend_publish' => true,
'backend_save' => true,
'backend_display' => true,
'backend_delete_entry' => true,
'frontend_entryproperties' => true,
'frontend_fetchentry' => true,
'xmlrpc_updertEntry' => true,
'xmlrpc_fetchEntry' => true,
'xmlrpc_deleteEntry' => true,
));
$propbag->add('groups', array('FRONTEND_ENTRY_RELATED', 'BACKEND_METAINFORMATION'));
$propbag->add('configuration', array('tag_names', 'default_description', 'default_keywords', 'escape'));
$this->supported_properties = array('meta_description', 'meta_keywords', 'meta_head_title');
}
function introspect_config_item($name, &$propbag) {
switch($name) {
case 'tag_names':
$propbag->add('type', 'string');
$propbag->add('name', PLUGIN_METADESC_TAGNAMES);
$propbag->add('description', PLUGIN_METADESC_TAGNAMES_DESC);
$propbag->add('default', 'b,strong');
break;
case 'default_description':
$propbag->add('type', 'string');
$propbag->add('name', PLUGIN_METADESC_DEFAULT_DESCRIPTION);
$propbag->add('description', PLUGIN_METADESC_DEFAULT_DESCRIPTION_DESC);
$propbag->add('default', '');
break;
case 'default_keywords':
$propbag->add('type', 'string');
$propbag->add('name', PLUGIN_METADESC_DEFAULT_KEYWORDS);
$propbag->add('description', PLUGIN_METADESC_DEFAULT_KEYWORDS_DESC);
$propbag->add('default', '');
break;
case 'escape':
$propbag->add('type', 'boolean');
$propbag->add('name', PLUGIN_METADESC_ESCAPE);
$propbag->add('description', PLUGIN_METADESC_ESCAPE_DESC);
$propbag->add('default', true);
break;
default:
return false;
}
return true;
}
function generate_content(&$title) {
$title = $this->title;
}
function extract_description($text) {
$x = strpos($text, '<p>');
if ($x === false) {
return substr(strip_tags($text), 0, 120);
}
$y = strpos($text, '</p>');
if ($y === false) {
return substr(strip_tags($text), 0, 120);
}
$title = substr($text, $x+3, $y-($x+3));
$title = strip_tags($title);
return $title;
}
function extract_keywords($text) {
$tag_names = $this->get_config('tag_names');
$tags = explode(",", $tag_names);
$tags_count = count($tags);
$results = array();
for ($i=0; $i < $tags_count; $i++) {
if (preg_match_all('/<' . $tags[$i] . '[^>]*>([^>]*)<\/' . $tags[$i] . '>/si', $text, $match)) {
$results = array_merge($results, $match[1]);
}
}
return $results;
}
function event_hook($event, &$bag, &$eventData, $addData = null) {
global $serendipity;
$hooks = &$bag->get('event_hooks');
if (isset($hooks[$event])) {
switch($event) {
case 'genpage':
// The 'genpage' hook is our last chance to modify Smarty
// variables before the template is called for the HTML head.
// Only modify the title on single-entry pages
if ($addData['view'] == 'entry') {
// Get the properties for this entry
$myid = $serendipity['GET']['id'];
// Requires a database fetch, but the only other way
// get the entry properties is to wait until we
// generate the entry; by the time that hook is
// called, the <title> tag has already been emitted.
// We need those properties now!
$property = serendipity_fetchEntryProperties($myid);
// Set a title, if one was defined for this entry
if (!empty($property['meta_head_title'])) {
// Make the variable name a little less unwieldy
$this->meta_title = $property['meta_head_title'];
$this->save_title = $serendipity['head_title'];
$this->save_subtitle = $serendipity['head_subtitle'];
$serendipity['head_title'] = (function_exists('serendipity_specialchars') ? serendipity_specialchars($this->meta_title) : htmlspecialchars($this->meta_title, ENT_COMPAT, LANG_CHARSET));
// Clear the subtitle (many templates use it along with the title)
$serendipity['head_subtitle'] = '';
}
}
return true;
break;
case 'frontend_header':
$default_description = $this->get_config('default_description');
$default_keywords = $this->get_config('default_keywords');
// Only emit in Single Entry Mode
if (($serendipity['GET']['id'] ?? 0) && $serendipity['view'] == 'entry') {
// we fetch the internal smarty object to get the current entry body
$entry = (array)$eventData['smarty']->tpl_vars['entry']->value;
// If we modified the <title>...
if (!empty($this->meta_title)) {
// We've messed up the banner. Put it back the way it was.
// Set smarty variables for banner back to normal "entry title - blog description"
$serendipity['smarty']->assign(
array(
'head_title' => $this->save_title,
'head_subtitle' => $this->save_subtitle
)
);
}
$meta_description = $entry['properties']['meta_description'] ?? '';
if (empty($meta_description)) {
$description_body = $entry['body'];
if (isset($entry['plaintext_body'])) {
$description_body = trim($entry['plaintext_body']);
}
$meta_description = $this->extract_description($description_body);
}
$meta_keywords = $entry['properties']['meta_keywords'] ?? '';
if (empty($meta_keywords)) {
$meta_keywords = (array)$this->extract_keywords($entry['body']);
if (!empty($meta_keywords))
{
$meta_keywords = implode(',', $meta_keywords);
} else {
// no entry specific keywords for this entry and extract_keywords was returned empty
$meta_keywords = $default_keywords;
}
}
if (serendipity_db_bool($this->get_config('escape'))) {
$md = (function_exists('serendipity_specialchars') ? serendipity_specialchars($meta_description) : htmlspecialchars($meta_description, ENT_COMPAT, LANG_CHARSET));
$mk = (function_exists('serendipity_specialchars') ? serendipity_specialchars($meta_keywords) : htmlspecialchars($meta_keywords, ENT_COMPAT, LANG_CHARSET));
} else {
$md = $meta_description;
$mk = $meta_keywords;
}
echo '<meta name="description" content="' . $md . '" />' . "\n";
if (!empty($meta_keywords))
{
echo ' <meta name="keywords" content="' . $mk . '" />' . "\n";
}
} else {
// emit default meta description and meta keyword, if not blank, for pages other than single entry
if (serendipity_db_bool($this->get_config('escape'))) {
$md = (function_exists('serendipity_specialchars') ? serendipity_specialchars($default_description) : htmlspecialchars($default_description, ENT_COMPAT, LANG_CHARSET));
$mk = (function_exists('serendipity_specialchars') ? serendipity_specialchars($default_keywords) : htmlspecialchars($default_keywords, ENT_COMPAT, LANG_CHARSET));
} else {
$md = $default_description;
$mk = $default_keywords;
}
if (!empty($default_description))
{
echo '<meta name="description" content="' . $md . '" />' . "\n";
}
if (!empty($default_keywords))
{
echo ' <meta name="keywords" content="' . $mk . '" />' . "\n";
}
}
break;
case 'backend_publish':
case 'backend_save':
if (!isset($serendipity['POST']['properties']) || !is_array($serendipity['POST']['properties']) || !isset($eventData['id'])) {
return true;
}
// Get existing data
$property = serendipity_fetchEntryProperties($eventData['id']);
foreach($this->supported_properties AS $prop_key) {
$prop_val = (isset($serendipity['POST']['properties'][$prop_key]) ? $serendipity['POST']['properties'][$prop_key] : null);
if (!isset($property[$prop_key]) && !empty($prop_val)) {
$q = "INSERT INTO {$serendipity['dbPrefix']}entryproperties (entryid, property, value) VALUES (" . (int)$eventData['id'] . ", '" . serendipity_db_escape_string($prop_key) . "', '" . serendipity_db_escape_string($prop_val) . "')";
} elseif (($property[$prop_key] ?? null) != $prop_val && !empty($prop_val)) {
$q = "UPDATE {$serendipity['dbPrefix']}entryproperties SET value = '" . serendipity_db_escape_string($prop_val) . "' WHERE entryid = " . (int)$eventData['id'] . " AND property = '" . serendipity_db_escape_string($prop_key) . "'";
} elseif (!empty($property[$prop_key]) && isset($prop_val) && empty($prop_val)) {
$q = "DELETE FROM {$serendipity['dbPrefix']}entryproperties WHERE entryid = " . (int)$eventData['id'] . " AND property = '" . serendipity_db_escape_string($prop_key) . "'";
} else {
// nothing to do
$q = '';
}
if (!empty($q)) serendipity_db_query($q);
}
return true;
break;
case 'backend_display':
if (isset($serendipity['POST']['properties']['meta_description'])) {
$meta_description = $serendipity['POST']['properties']['meta_description'];
} elseif (isset($eventData['properties']['meta_description'])) {
$meta_description = $eventData['properties']['meta_description'];
} else {
$meta_description = '';
}
if (isset($serendipity['POST']['properties']['meta_keywords'])) {
$meta_keywords = $serendipity['POST']['properties']['meta_keywords'];
} elseif (isset($eventData['properties']['meta_keywords'])) {
$meta_keywords = $eventData['properties']['meta_keywords'];
} else {
$meta_keywords = '';
}
if (isset($serendipity['POST']['properties']['meta_head_title'])) {
$meta_head_title = $serendipity['POST']['properties']['meta_head_title'];
} elseif (isset($eventData['properties']['meta_head_title'])) {
$meta_head_title = $eventData['properties']['meta_head_title'];
} else {
$meta_head_title = '';
}
?>
<fieldset style="margin: 5px">
<legend><?php echo PLUGIN_METADESC_NAME; ?></legend>
<p class="meta_description"><em><?php echo PLUGIN_METADESC_FORM; ?></em></p>
<label for="serendipity[properties][meta_description]"><?php echo PLUGIN_METADESC_DESCRIPTION; ?></label><br />
<input class="input_textbox" type="text" style="width: 100%" value="<?php echo (function_exists('serendipity_specialchars') ? serendipity_specialchars($meta_description) : htmlspecialchars($meta_description, ENT_COMPAT, LANG_CHARSET)); ?>" name="serendipity[properties][meta_description]" id="properties_meta_description" />
<span class="meta_string_length"><?php echo PLUGIN_METADESC_LENGTH . ': ' . str_word_count($meta_description) . ' '. PLUGIN_METADESC_WORDS . ', ' . strlen($meta_description) . ' ' . PLUGIN_METADESC_CHARACTERS; ?></span>
<br /><br />
<label for="serendipity[properties][meta_keywords]"><?php echo PLUGIN_METADESC_KEYWORDS; ?></label><br />
<input class="input_textbox" type="text" style="width: 100%" value="<?php echo (function_exists('serendipity_specialchars') ? serendipity_specialchars($meta_keywords) : htmlspecialchars($meta_keywords, ENT_COMPAT, LANG_CHARSET)); ?>" name="serendipity[properties][meta_keywords]" id="properties_meta_keywords" />
<span class="meta_string_length"><?php echo PLUGIN_METADESC_LENGTH . ': ' . str_word_count($meta_keywords) . ' '. PLUGIN_METADESC_WORDS . ', ' . strlen($meta_keywords) . ' ' . PLUGIN_METADESC_CHARACTERS; ?></span>
<br /><br />
<p class="meta_description"><em><?php echo PLUGIN_METADESC_HEADTITLE_DESC; ?></em></p>
<label for="serendipity[properties][meta_head_title]"><?php echo PLUGIN_METADESC_HEADTITLE; ?></label><br />
<input class="input_textbox" type="text" style="width: 100%" value="<?php echo (function_exists('serendipity_specialchars') ? serendipity_specialchars($meta_head_title) : htmlspecialchars($meta_head_title, ENT_COMPAT, LANG_CHARSET)); ?>" name="serendipity[properties][meta_head_title]" id="properties_headtitle" />
<span class="meta_string_length"><?php echo PLUGIN_METADESC_LENGTH . ': ' . str_word_count($meta_head_title) . ' '. PLUGIN_METADESC_WORDS . ', ' . strlen($meta_head_title) . ' ' . PLUGIN_METADESC_CHARACTERS; ?></span>
<p class="meta_stringlength_disclaimer"><em><?php echo '<sup>*</sup> ' . PLUGIN_METADESC_STRINGLENGTH_DISCLAIMER; ?></em></p>
</fieldset>
<?php
return true;
break;
case 'xmlrpc_deleteEntry':
case 'backend_delete_entry':
$q = "DELETE FROM {$serendipity['dbPrefix']}entryproperties WHERE entryid = " . (int)$eventData['id'] . " AND property LIKE '%meta_%'";
serendipity_db_query($q);
return true;
break;
case 'frontend_entryproperties':
if (class_exists('serendipity_event_entryproperties') || !is_array($addData)) {
// Fetching of properties is already done there, so this is just for poor users who don't have the entryproperties plugin enabled
return true;
}
$q = "SELECT entryid, property, value FROM {$serendipity['dbPrefix']}entryproperties WHERE entryid IN (" . implode(', ', array_keys($addData)) . ") AND property LIKE '%meta_%'";
$properties = serendipity_db_query($q);
if (!is_array($properties)) {
return true;
}
foreach($properties AS $idx => $row) {
$eventData[$addData[$row['entryid']]]['properties'][$row['property']] = $row['value'];
}
return true;
break;
/* MAYBE FOR FUTURE
case 'frontend_fetchentry':
$cond = "meta_d.value AS meta_description,\n";
$cond .= "meta_k.value AS meta_keywords,\n";
if (empty($eventData['addkey'])) {
$eventData['addkey'] = $cond;
} else {
$eventData['addkey'] .= $cond;
}
$cond = "\nLEFT OUTER JOIN {$serendipity['dbPrefix']}entryproperties meta_d
ON (e.id = meta_d.entryid AND meta_d.property = 'meta_description')";
$cond .= "\nLEFT OUTER JOIN {$serendipity['dbPrefix']}entryproperties meta_k
ON (e.id = meta_k.entryid AND meta_d.property = 'meta_keywords')";
if (empty($eventData['joins'])) {
$eventData['joins'] = $cond;
} else {
$eventData['joins'] .= $cond;
}
return true;
break;
*/
case 'xmlrpc_updertEntry':
if (isset($eventData['id'])) {
//XMLRPC call
if (!empty($eventData['mt_keywords'])) {
$property = serendipity_fetchEntryProperties($eventData['id']);
if (!isset($property['meta_keywords'])) {
$q = "INSERT INTO {$serendipity['dbPrefix']}entryproperties (entryid, property, value) VALUES (" . (int)$eventData['id'] . ", 'meta_keywords', '" . serendipity_db_escape_string($eventData['mt_keywords']) . "')";
} elseif ($property['mt_keywords'] != $eventData['mt_keywords']) {
$q = "UPDATE {$serendipity['dbPrefix']}entryproperties SET value = '" . serendipity_db_escape_string($eventData['mt_keywords']) . "' WHERE entryid = " . (int)$eventData['id'] . " AND property = 'meta_keywords'";
} else {
$q = "DELETE FROM {$serendipity['dbPrefix']}entryproperties WHERE entryid = " . (int)$eventData['id'] . " AND property = 'meta_keywords'";
}
serendipity_db_query($q);
}
}
return true;
break;
case 'xmlrpc_fetchEntry':
if (isset($eventData['id'])) {
//XMLRPC call
$q = "SELECT entryid, property, value FROM {$serendipity['dbPrefix']}entryproperties WHERE entryid IN (" . $eventData['id'] . ") AND property LIKE '%meta_keywords%'";
$properties = serendipity_db_query($q);
if (!is_array($properties)) {
return true;
}
//wow, this is hack... is there a better way?
$properties = $properties[0];
$eventData['mt_keywords']=$properties['value'];
}
return true;
break;
default:
return false;
break;
}
return true;
} else {
return false;
}
}
}
/* vim: set sts=4 ts=4 expandtab : */