Last active
February 10, 2021 17:08
-
-
Save advanceboy/87140e2ea2a4a122bbcbd70f8ee9590f to your computer and use it in GitHub Desktop.
Hotfix for Pz-LinkCard v2.4.2.2 that fixes the error "pz-linkcard: Incorrect URL specification. (url=)" in Pz-LinkCard v2.4.2.2.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/* | |
Plugin Name: Pz-LinkCard | |
Plugin URI: http://poporon.poponet.jp/pz-linkcard | |
Description: リンクをカード形式で表示します。 | |
Version: 2.4.2.2-pl210211hotfix | |
Author: poporon | |
Author URI: http://poporon.poponet.jp | |
License: GPLv2 or later | |
*/ | |
defined('ABSPATH') || die; | |
class Pz_LinkCard { | |
private $slug; // スラッグ | |
private $text_domain; // テキスト ドメイン(スラッグと同じ内容) | |
private $charset; // 文字セット | |
private $amp; // Google AMP | |
private $now; // 現在日時(ローカル時間) | |
private $now_mysql; // 現在日時(SQL形式) | |
private $plugin_basename; // プラグイン ディレクトリの名前 | |
private $plugin_dir_path; // プラグイン ディレクトリのパス | |
private $plugin_dir_url; // プラグイン ディレクトリのURL | |
private $plugin_link; // プラグインページのURL | |
private $upload_dir_path; // アップロード ディレクトリのパス | |
private $upload_dir_url; // アップロード ディレクトリのURL | |
private $db_name; // DB名 | |
private $options; // パラメータ | |
protected $defaults = array( | |
'plugin-link' => null, | |
'plugin-url' => 'https://popozure.info/pz-linkcard', | |
'plugin-name' => 'Pz-LinkCard', | |
'plugin-version' => '2.4.2.2', | |
'flg-invalid' => null, | |
'invalid-url' => null, | |
'invalid-time' => null, | |
'special-format' => null, | |
'link-all' => 1, | |
'margin-top' => '4px', | |
'margin-right' => '16px', | |
'margin-bottom' => '16px', | |
'margin-left' => '4px', | |
'card-top' => null, | |
'card-right' => null, | |
'card-bottom' => null, | |
'card-left' => null, | |
'width' => '500px', | |
'content-height' => '108px', | |
'centering' => null, | |
'blockquote' => null, | |
'info-position' => 1, | |
'use-sitename' => 1, | |
'display-date' => 1, | |
'heading' => null, | |
'flg-anker' => 1, | |
'separator' => null, | |
'display-url' => 1, | |
'thumbnail-position' => 2, | |
'thumbnail-width' => '100px', | |
'thumbnail-height' => '108px', | |
'thumbnail-shadow' => null, | |
'content-inset' => null, | |
'display-excerpt' => 1, | |
'shadow-inset' => null, | |
'shadow' => null, | |
'radius' => null, | |
'hover' => null, | |
'border-style' => 'solid', | |
'border-width' => '1px', | |
'style-reset-img' => 1, | |
'flg-more' => null, | |
'sns-position' => 2, | |
'sns-tw' => 1, | |
'sns-fb' => 1, | |
'sns-hb' => 1, | |
'sns-po' => 1, | |
'color-title' => '#111111', | |
'color-url' => '#4466ff', | |
'color-excerpt' => '#333333', | |
'color-more' => '#444444', | |
'color-info' => '#222222', | |
'color-added' => '#222222', | |
'color-plugin' => '#888888', | |
'outline-title' => null, | |
'outline-url' => null, | |
'outline-excerpt' => null, | |
'outline-more' => null, | |
'outline-info' => null, | |
'outline-added' => null, | |
'outline-plugin' => null, | |
'outline-color-title' => '#ffffff', | |
'outline-color-url' => '#ffffff', | |
'outline-color-excerpt' => '#ffffff', | |
'outline-color-more' => '#ffffff', | |
'outline-color-info' => '#ffffff', | |
'outline-color-added' => '#ffffff', | |
'outline-color-plugin' => '#ffffff', | |
'size-title' => '16px', | |
'size-url' => '10px', | |
'size-excerpt' => '11px', | |
'size-more' => '12px', | |
'size-info' => '12px', | |
'size-added' => '12px', | |
'size-plugin' => '10px', | |
'height-title' => '24px', | |
'height-url' => '10px', | |
'height-excerpt' => '17px', | |
'height-more' => '40px', | |
'height-info' => '12px', | |
'height-added' => '12px', | |
'height-plugin' => '10px', | |
'trim-title' => 80, | |
'trim-url' => 250, | |
'trim-excerpt' => 500, | |
'trim-info' => 200, | |
'nowrap-title' => null, | |
'nowrap-url' => 1, | |
'thumbnail-resize' => 1, | |
'ex-border-color' => '#888888', | |
'ex-bgcolor' => '#ffffff', | |
'ex-image' => null, | |
'ex-thumbnail' => 13, | |
'ex-favicon' => 3, | |
'ex-info' => null, | |
'ex-more-text' => null, | |
'ex-target' => 2, | |
'nofollow' => null, | |
'noopener' => 1, | |
'use-hatena' => null, | |
'in-border-color' => '#888888', | |
'in-bgcolor' => '#f8f8f8', | |
'in-image' => null, | |
'in-thumbnail' => 1, | |
'in-favicon' => 3, | |
'in-info' => null, | |
'in-more-text' => null, | |
'in-target' => null, | |
'in-get' => null, | |
'flg-get-pid' => null, | |
'th-border-color' => '#888888', | |
'th-bgcolor' => '#eeeeee', | |
'th-image' => null, | |
'th-info' => null, | |
'favicon-api' => 'https://www.google.com/s2/favicons?domain=%DOMAIN%', | |
'thumbnail-api' => 'https://s.wordpress.com/mshots/v1/%URL%?w=100', | |
'cache-image-size' => 200, | |
'thumbnail-dir' => null, | |
'thumbnail-url' => null, | |
'css-url' => null, | |
'css-url-add' => null, | |
'css-add' => null, | |
'css-count' => 0, | |
'css-path' => null, | |
'css-templete' => null, | |
'flg-unlink' => 1, | |
'flg-ssl' => 1, | |
'flg-redir' => 1, | |
'flg-referer' => 1, | |
'flg-agent' => 1, | |
'user-agent' => null, | |
'flg-alive' => 1, | |
'flg-alive-count' => null, | |
'flg-subdir' => 1, | |
'code1' => 'blogcard', | |
'use-inline' => null, | |
'code2' => null, | |
'code3' => null, | |
'code4' => null, | |
'auto-atag' => null, | |
'auto-url' => null, | |
'auto-external' => null, | |
'flg-do-shortcode' => 1, | |
'flg-edit-insert' => 1, | |
'flg-edit-qtag' => 1, | |
'trail-slash' => '1', | |
'class-pc' => null, | |
'class-mobile' => null, | |
'flg-amp-url' => null, | |
'flg-idn' => 1, | |
'flg-relative-url' => null, | |
'flg-invalid-hide' => null, | |
'saved-date' => null, | |
'debug-time' => null, | |
'initialize' => null | |
); | |
public function __construct() { | |
$this->slug = basename(dirname(__FILE__)); | |
$this->text_domain = $this->slug; | |
$this->charset = get_bloginfo('charset'); | |
$this->amp = '1'; | |
$this->now = current_time('timestamp', false); | |
$this->now_mysql = current_time('mysql'); | |
$this->plugin_basename = plugin_basename(__FILE__); | |
$this->plugin_dir_path = plugin_dir_path(__FILE__); | |
$this->plugin_dir_url = plugin_dir_url (__FILE__); | |
$wp_upload_dir = wp_upload_dir(); | |
$this->upload_dir_path = $wp_upload_dir['basedir'].'/'.$this->slug.'/'; | |
$this->upload_dir_url = $wp_upload_dir['baseurl'].'/'.$this->slug.'/'; | |
// オプション読み込み | |
$this->options = get_option('Pz_LinkCard_options', $this->defaults ); | |
foreach ($this->defaults as $key => $value) { | |
if (!isset($this->options[$key])) { | |
$this->options[$key] = null; | |
} | |
} | |
// DB | |
global $wpdb; | |
$this->db_name = $wpdb->prefix.'pz_linkcard'; | |
// バージョンが違っていたら、DBとオプションを更新する | |
if ($this->options['plugin-version'] <> $this->defaults['plugin-version']) { | |
$this->activate(); | |
} | |
// 日本語化 | |
load_plugin_textdomain ($this->text_domain, false, $this->slug.'/languages'); | |
// 管理画面のとき | |
if (is_admin()) { | |
register_activation_hook (__FILE__, array($this, 'activate') ); // プラグインを有効化するときの処理 | |
register_deactivation_hook (__FILE__, array($this, 'deactivate') ); // プラグインを無効化するときの処理 | |
add_action ('admin_menu', array($this, 'add_menu') ); // 設定メニュー | |
add_action ('admin_enqueue_scripts', array($this, 'enqueue_admin') ); // 設定メニュー用スクリプト | |
add_action ('admin_print_footer_scripts', array($this, 'add_footer') ); // テキストエディタ用クイックタグ | |
add_action ('admin_notices', array($this, 'add_notices')); // 注意書き | |
add_filter ('mce_buttons', array($this, 'add_mce_button') ); // ビジュアルエディタ用ボタン | |
add_filter ('mce_external_plugins', array($this, 'add_mce_plugin') ); // ビジュアルエディタ用ボタン | |
add_filter ('plugin_action_links_'.$this->plugin_basename, array($this, 'action_links') ); // プラグイン画面 | |
} else { | |
add_action ('wp_enqueue_scripts', array($this, 'enqueue') ); // スタイルシート呼び出し | |
if ($this->options['auto-atag'] || $this->options['auto-url']) { // 自動置き換え | |
add_filter ('the_content', array($this, 'auto_replace') ); | |
add_shortcode ('pz-linkcard-auto-replace', array($this, 'shortcode') ); | |
} | |
if ($this->options['code1']) { // ショートコード1 | |
add_shortcode($this->options['code1'], array($this, 'shortcode')); | |
} | |
if ($this->options['code2']) { // ショートコード2 | |
add_shortcode($this->options['code2'], array($this, 'shortcode')); | |
} | |
if ($this->options['code3']) { // ショートコード3 | |
add_shortcode($this->options['code3'], array($this, 'shortcode')); | |
} | |
if ($this->options['code4']) { // ショートコード4 | |
add_shortcode($this->options['code4'], array($this, 'shortcode')); | |
} | |
} | |
// SNS更新、リンク先チェック | |
add_action( 'pz_linkcard_check', array( $this, 'schedule_hook_check' ) ); | |
add_action( 'pz_linkcard_alive', array( $this, 'schedule_hook_alive' ) ); | |
if (!wp_next_scheduled('pz_linkcard_check')) { | |
wp_schedule_event ( time() + 10 , 'hourly', 'pz_linkcard_check'); | |
} | |
if (!wp_next_scheduled('pz_linkcard_alive')) { | |
wp_schedule_event ( time() + 1800 , 'daily', 'pz_linkcard_alive'); | |
} | |
} | |
// テキストリンクの行とURLのみの行をリンクカードへ置き換える処理(直接HTMLタグにするのでは無くショートコードに変換する。) | |
public function auto_replace($content ) { | |
if (!$this->options['auto-external'] ) { | |
if ($this->options['auto-atag'] ) { | |
$content = preg_replace('/(^|<br ?\/?>)(<p.*>)?<a .*href=[\'"](https?:\/\/[-_\.!~*()a-zA-Z0-9;\/?:\@&=+\$,%#]+)[\'"]((?!<IMG).)*<\/a>(<\/p>)?$/im', '[pz-linkcard-auto-replace url="$3"]', $content ); | |
} | |
if ($this->options['auto-url'] ) { | |
$content = preg_replace('/(^|<br ?\/?>)(<p.*>)?(https?:\/\/[-_\.!~*()a-zA-Z0-9;\/?:\@&=+\$,%#]+)(<\/p>|<br ?\/?>)?$/im', '[pz-linkcard-auto-replace url="$3"]', $content ); | |
} | |
if ($this->options['flg-do-shortcode'] && ($this->options['auto-atag'] || $this->options['auto-url'] ) ) { | |
$content = do_shortcode($content ); | |
} | |
return $content; | |
} else { | |
if ($this->options['auto-atag'] ) { | |
preg_match_all('/(^|<br ?\/?>)(<p.*>)?(<a .*href=[\'"](https?:\/\/[-_\.!~*()a-zA-Z0-9;\/?:\@&=+\$,%#]+)[\'"]((?!<IMG).)*<\/a>)(<\/p>)?$/im', $content, $m ); | |
for ($i = 0; $i < count($m[0]); $i++ ) { | |
$url = $m[4][$i]; | |
if ($this->Pz_LinkType($url ) == 0 ) { | |
$tag = '[pz-linkcard-auto-replace url="'.$url.'"]'; | |
$content = preg_replace('{'.$m[0][$i].'}', $tag, $content, 1 ); | |
} | |
} | |
} | |
if ($this->options['auto-url'] ) { | |
preg_match_all('/(^|<br ?\/?>)(<p.*>)?(https?:\/\/[-_\.!~*()a-zA-Z0-9;\/?:\@&=+\$,%#]+)(<\/p>|<br ?\/?>)?$/im', $content, $m ); | |
for ($i = 0; $i < count($m[0]); $i++ ) { | |
$url = $m[3][$i]; | |
if ($this->Pz_LinkType($url ) == 0) { | |
$tag = '[pz-linkcard-auto-replace url="'.$url.'"]'; | |
$content = preg_replace('{'.$m[0][$i].'}', $tag, $content, 1 ); | |
} | |
} | |
} | |
if ($this->options['flg-do-shortcode'] && ($this->options['auto-atag'] || $this->options['auto-url'] ) ) { | |
$content = do_shortcode($content ); | |
} | |
return $content; | |
} | |
} | |
// ショートコード処理 | |
public function shortcode($atts, $content = null, $shortcode ) { | |
// 実行時間 | |
if ($this->options['debug-time']) { | |
$start_time = microtime(true); | |
echo PHP_EOL.'<!-- Pz-LkC [Debug mode: On] /-->'.PHP_EOL; | |
echo '<!-- Pz-LkC [shortcode]'.PHP_EOL; | |
echo '$atts='.html_entity_decode(print_r($atts, true ) ); | |
echo '$content="'.html_entity_decode($content ).'"'.PHP_EOL; | |
echo '$shortcode="'.html_entity_decode($shortcode ).'"'.PHP_EOL; | |
echo '/-->'.PHP_EOL; | |
} | |
// URLパラメータ | |
if (!empty($atts['url'] ) ) { | |
$url = $atts['url']; | |
} elseif (!empty($atts['href'] ) ) { // Aタグのようにhrefパラメータも有効にする | |
$url = $atts['href']; | |
} elseif (!empty($atts['uri'] ) ) { // 密かに記述ミス対応(uriやurIでもurlとして判定する) | |
$url = $atts['uri']; | |
} elseif (!empty($atts['ur1'] ) ) { // 密かに記述ミス対応(ur1でもurlとして判定する) | |
$url = $atts['ur1']; | |
} elseif (!empty($atts[0]) && preg_match('/url=[\s \'\"‘’“”″]*(.*?)[\s \'\"‘’“”″]*$/u', $atts[0], $m) ) { // 謎の記述ミスに対応 | |
$url = $m[1]; | |
} elseif (!empty($atts[1]) && preg_match('/url=[\s \'\"‘’“”″]*(.*?)[\s \'\"‘’“”″]*$/u', $atts[1], $m) ) { // 謎の記述ミスに対応 | |
$url = $m[1]; | |
} elseif (!empty($atts[0]) && preg_match('/href\s*=\s*(?:(?P<quo>[\'\"‘’“”″])(?P<url1>.*?)(?P=quo)|(?P<url2>[^ <>\'\"`=]+))/u', $atts[0], $m) ) { // URL が HTML リンクに書き換わって $atts に渡される際の、不可解な shortcode 動作に対応 | |
$url = empty($m['url1']) ? $m['url2'] : $m['url1']; | |
} elseif (!empty($atts[1]) && preg_match('/href\s*=\s*(?:(?P<quo>[\'\"‘’“”″])(?P<url1>.*?)(?P=quo)|(?P<url2>[^ <>\'\"`=]+))/u', $atts[1], $m) ) { // URL が HTML リンクに書き換わって $atts に渡される際の、不可解な shortcode 動作に対応 | |
$url = empty($m['url1']) ? $m['url2'] : $m['url1']; | |
} else { | |
$url = null; | |
} | |
$url_org = $url; // 指定されたurlパラメータ(エラー表示用) | |
if ($this->options['flg-relative-url'] && substr($url, 0, 1) == '/') { | |
$url = home_url().$url; // 相対パスを絶対パスに変換 | |
} | |
$url = $this->pz_TrimURL($url ); // URLエンティティ化など(無害化?) | |
if (!$url ) { | |
if (!$this->options['flg-invalid']) { | |
$url_now = get_permalink(); | |
$post_id = url_to_postid($url_now ); | |
if ($post_id) { | |
$this->options['flg-invalid'] = true; | |
$this->options['invalid-url'] = $url_now; | |
$this->options['invalid-time'] = $this->now; | |
$result = update_option('Pz_LinkCard_options', $this->options); | |
} | |
} | |
return '<div id="lkc-error" class="lkc-error"><div class="lkc-card"><div class="lkc-this-wrap"><div class="lkc-excerpt">'.$this->slug.': '.__('Incorrect URL specification.', $this->text_domain).'(url='.html_entity_decode($url_org).')'.PHP_EOL.'<!-- '.html_entity_decode(print_r($atts, true)).' /-->'.PHP_EOL.'</div></div></div></div>'; | |
} | |
$atts['url'] = $url; | |
// titleパラメータ | |
if (!isset($atts['title'] ) ) { | |
$atts['title'] = null; | |
} | |
// contentパラメータ | |
if (!isset($atts['excerpt'] ) ) { | |
if (isset($atts['content'] ) ) { | |
$atts['excerpt'] = $atts['content']; | |
} elseif (isset($atts['contents'] ) ) { | |
$atts['excerpt'] = $atts['contents']; | |
} elseif (isset($atts['description'] ) ) { | |
$atts['excerpt'] = $atts['description']; | |
} else { | |
$atts['excerpt'] = null; | |
} | |
} | |
// 囲まれ文字(ショートコード1のみ有効) | |
if ($shortcode == $this->options['code1']) { | |
switch (isset($this->options['use-inline']) ? $this->options['use-inline'] : null ) { | |
case '1': | |
$atts['excerpt'] = isset($content) ? $content : null; | |
break; | |
case '2': | |
$atts['title'] = isset($content) ? $content : null; | |
break; | |
} | |
} | |
// 記事内容取得 | |
$tag = $this->pz_GetHTML($atts ); | |
// 実行時間 | |
if ($this->options['debug-time']) { | |
$end_time = microtime(true); | |
$elasped_time = number_format($end_time - $start_time, 8, '.', ','); | |
echo '<!-- Pz-LkC [shortcode]'.PHP_EOL; | |
echo 'ElaspedTime='.$elasped_time.'sec'.PHP_EOL; | |
echo '] /-->'.PHP_EOL; | |
} | |
return $tag; | |
} | |
// キャッシュやリンク先からリンクカードのHTMLを生成 | |
private function pz_GetHTML($atts ) { | |
if ($this->options['debug-time']) { | |
echo '<!-- Pz-LkC [pz_GetHTML]'.PHP_EOL; | |
echo '$atts='.html_entity_decode(print_r($atts, true ) ); | |
echo '/-->'.PHP_EOL; | |
} | |
// 変数の用意 | |
$is_mobile = false; | |
$url = (isset($atts['url']) ? $atts['url'] : null); | |
// URL | |
if (!$url ) { | |
return null; | |
} | |
// モバイルチェック | |
if (function_exists('wp_is_mobile') && wp_is_mobile() ) { | |
$is_mobile = true; | |
} | |
if ($this->options['debug-time'] ) { | |
echo '<!-- Pz-LkC [pz_GetHTML] $is_mobile="'.$is_mobile.'" /-->'.PHP_EOL; | |
} | |
// URLパース(ドメイン名などを抽出) | |
$url_m = parse_url($url ); | |
$scheme = isset($url_m['scheme']) ? $url_m['scheme'] : null; // スキーム | |
$domain = isset($url_m['host']) ? $url_m['host'] : null; // ドメイン名 | |
$domain_url = isset($url_m['host']) ? $scheme.'://'.$url_m['host'] : null; // ドメインURL | |
$location = isset($url_m['path']) ? $url_m['path'] : null; // ドメイン名以降 | |
// 自サイトチェック | |
$link_type = $this->Pz_LinkType($url ); | |
// モバイルかPCかのクラス名を追加 | |
$class_id = 'linkcard'; | |
if ($is_mobile && $this->options['class-mobile'] ) { | |
$class_id .= ' '.$this->options['class-mobile']; | |
} elseif ($this->options['class-pc']) { | |
$class_id .= ' '.$this->options['class-pc']; | |
} | |
// キャッシュから取得 | |
$data_id = null; | |
$data = array(); | |
$data['url'] = $url; | |
$result = $this->pz_GetCache( $data ); | |
if (isset($result) && is_array($result) && isset($result['url'])) { | |
$data = $result; | |
$data_id = $data['id']; | |
$url = $data['url']; | |
} | |
if ($this->options['debug-time']) { | |
echo '<!-- Pz-LkC [pz_GetHTML] get from cache $data_id="'.$data_id.'" /-->'.PHP_EOL; | |
} | |
// 内部リンクの処理 | |
if ( $link_type ) { | |
if ($this->options['debug-time']) { | |
echo '<!-- Pz-LkC [pz_GetHTML] Internal link /-->'.PHP_EOL; | |
} | |
// リンクターゲットの設定 | |
$target = ''; // 同ページに開く | |
if (isset($this->options['in-target'])) { | |
if ($this->options['in-target'] == '1' || ($this->options['in-target'] == '2' && !$is_mobile)) { | |
$target = ' target="_blank"'; // 新しいページで開く | |
} | |
} | |
// nofollowの指定 | |
$rel = ''; | |
if ( (isset($atts['follow'] ) && mb_strtolower($atts['follow']) == 'no') || (isset($atts['nofollow'] ) && mb_strtolower($atts['nofollow']) == 'true') ) { | |
$rel = ' rel="nofollow"'; // 要望により内部リンクでもnofollow可能(ショートコードのパラメータで指定時のみ) | |
} | |
// キャッシュが無い、もしくは強制取得 | |
if ( is_null($data_id) || ( isset($atts['force']) && $atts['force'] == true ) ) { | |
$data = $this->pz_GetPost($data ); // 最新記事内容を取得 | |
$data['link_type'] = 1; | |
$result = $this->pz_SetCache($data ); // 保存 | |
} elseif ($this->options['in-get'] <> 2) { | |
$data = $this->pz_GetPost( $data ); // 最新記事内容を取得 | |
$data['link_type'] = 1; | |
} | |
} | |
// 外部リンクの処理 | |
if ( !$link_type ) { | |
if ($this->options['debug-time']) { | |
echo '<!-- Pz-LkC [pz_GetHTML] External link /-->'.PHP_EOL; | |
} | |
// リンクターゲットの設定 | |
$target = null; // 同ページに開く | |
if (isset($this->options['ex-target'] ) ) { | |
if ($this->options['ex-target'] == '1' || ($this->options['ex-target'] == '2' && !$is_mobile ) ) { | |
$target = ' target="_blank"'; // 新しいタブで開く | |
} | |
} | |
// noopenerとnofollowの指定 | |
$rel = 'external'; | |
if ($this->options['nofollow'] || (isset($atts['follow'] ) && mb_strtolower($atts['follow']) == 'no') || (isset($atts['nofollow'] ) && mb_strtolower($atts['nofollow']) == 'true') ) { | |
$rel .= ' nofollow'; // nofollow指定。趣味の問題? | |
} | |
if ($this->options['noopener']) { | |
$rel .= ' noopenner'; | |
} | |
$rel = ' rel="'.$rel.'"'; | |
// キャッシュが無い、もしくは強制取得 | |
if ( is_null($data_id) || ( isset($atts['force']) && $atts['force'] == true ) ) { | |
$result = $this->pz_GetCURL( $data ); // cURLで記事内容を取得 | |
if ( isset($result) && is_array($result) && isset($result['url']) ) { | |
$data = $result; | |
$data['link_type'] = 0; | |
$result = $this->pz_SetCache( $data ); | |
} | |
} | |
} | |
// 念のため初期化 | |
$data_id = isset($data['id']) ? $data['id'] : null; | |
$site_name = isset($data['site_name']) ? $data['site_name'] : null; | |
$title = isset($data['title']) ? $data['title'] : null; | |
$excerpt = isset($data['excerpt']) ? $data['excerpt'] : null; | |
$post_date = isset($data['post_date']) ? $data['post_date'] : null; | |
$thumbnail_url = isset($data['thumbnail']) ? $data['thumbnail'] : null; | |
$favicon_url = isset($data['favicon']) ? $data['favicon'] : null; | |
$result_code = isset($data['result_code']) ? $data['result_code'] : null; | |
$sns_tw = isset($data['sns_twitter']) ? $data['sns_twitter'] : null; | |
$sns_fb = isset($data['sns_facebook']) ? $data['sns_facebook'] : null; | |
$sns_hb = isset($data['sns_hatena']) ? $data['sns_hatena'] : null; | |
$sns_po = isset($data['sns_pocket']) ? $data['sns_pocket'] : null; | |
$alive_result = isset($data['alive_result']) ? $data['alive_result'] : null; | |
$thumbnail = null; | |
$favicon = null; | |
// ラッピング | |
switch ($link_type) { | |
case '1': | |
$wrap_op = '<div class="lkc-this-wrap">'; | |
$wrap_cl = '</div>'; | |
$added_op = '<div class="lkc-this-added">'; | |
$added_cl = '</div>'; | |
$more = null; | |
$more_text = null; | |
$info = isset($this->options['th-info']) ? $this->options['th-info'] : null ; | |
$sw_thumbnail = isset($this->options['in-thumbnail']) ? $this->options['in-thumbnail'] : 0 ; | |
$sw_favicon = isset($this->options['in-favicon']) ? $this->options['in-favicon'] : 0 ; | |
break; | |
case '2': | |
$wrap_op = '<div class="lkc-internal-wrap">'; | |
$wrap_cl = '</div>'; | |
$added_op = '<div class="lkc-internal-added">'; | |
$added_cl = '</div>'; | |
$more = isset($this->options['flg-more']) ? $this->options['flg-more'] : null ; | |
$more_text = isset($this->options['in-more-text']) ? $this->options['in-more-text'] : null ; | |
$info = isset($this->options['in-info']) ? $this->options['in-info'] : null ; | |
$sw_thumbnail = isset($this->options['in-thumbnail']) ? $this->options['in-thumbnail'] : 0 ; | |
$sw_favicon = isset($this->options['in-favicon']) ? $this->options['in-favicon'] : 0 ; | |
break; | |
default: | |
$wrap_op = '<div class="lkc-external-wrap">'; | |
$wrap_cl = '</div>'; | |
$added_op = '<div class="lkc-external-added">'; | |
$added_cl = '</div>'; | |
$more = isset($this->options['flg-more']) ? $this->options['flg-more'] : null ; | |
$more_text = isset($this->options['ex-more-text']) ? $this->options['ex-more-text'] : null ; | |
$info = isset($this->options['ex-info']) ? $this->options['ex-info'] : null ; | |
$sw_thumbnail = isset($this->options['ex-thumbnail']) ? $this->options['ex-thumbnail'] : 0 ; | |
$sw_favicon = isset($this->options['ex-favicon']) ? $this->options['ex-favicon'] : 0 ; | |
break; | |
} | |
// 外部リンクの処理 | |
if ( !$link_type && isset($this->options['use-hatena']) && !is_null($this->options['use-hatena'] ) ) { | |
// 「はてなブログカード」をそのまま利用する | |
$tag = '<div class="lkc-iframe-wrap"><iframe src="https://hatenablog-parts.com/embed?url=' .$url.'" class="lkc-iframe" scrolling="no" frameborder="0"></iframe></div>'; | |
if (isset($this->options['blockquote']) ? $this->options['blockquote'] : null == '1') { | |
$tag = '<div class="'.$class_id.'"><blockquote class="lkc-quote">'.$tag.'</blockquote></div>'; | |
} else { | |
$tag = '<div class="'.$class_id.'">'.$tag.'</div>'; | |
} | |
return $tag; // タグを出力してさっさと終了 | |
} | |
// サムネイル取得 | |
if ( !$this->options['thumbnail-position'] || ( $result_code <> 0 && $result_code <> 200 ) ) { | |
$thumbnail = null; | |
} else { | |
if ($sw_thumbnail == 1 || $sw_thumbnail == 13 ) { // 直接取得 | |
if (!$link_type ) { | |
$thumbnail_url = $this->pz_GetThumbnail($thumbnail_url ); // 外部サイトのサムネイルをキャッシュ | |
} | |
if (isset($thumbnail_url ) && $thumbnail_url <> '' ) { | |
$thumbnail = '<img class="lkc-thumbnail-img" src="'.$thumbnail_url.'" alt="" />'; | |
} elseif ($sw_thumbnail == 13) { // 直接取得に失敗 | |
$sw_thumbnail = 3; | |
} | |
} | |
if ($sw_thumbnail == 3 ) { // WebAPIを利用 | |
// 画像取得(WebAPI) | |
if (isset($this->options['thumbnail-api'] ) ) { | |
$thumbnail = preg_replace('/%DOMAIN_URL%/', $domain_url, $this->options['thumbnail-api'] ); | |
$thumbnail = preg_replace('/%DOMAIN%/', $domain, $thumbnail); | |
$thumbnail = preg_replace('/%URL%/', rawurlencode($url ), $thumbnail ); | |
$thumbnail = '<img class="lkc-thumbnail-img" src="'.$thumbnail.'" alt="" />'; | |
} | |
} | |
} | |
// ファビコン取得 | |
if (!isset($this->options['info-position'] ) ) { | |
$favicon = null; | |
} else{ | |
if ($sw_favicon == 1 || $sw_favicon == 13 ) { // 直接取得 | |
if (!is_null($favicon_url ) ) { | |
$favicon = '<img class="lkc-favicon" src="'.$favicon_url.'" alt="" width=16 height=16 />'; | |
} elseif ($sw_favicon == 13 ) { // 直接取得に失敗 | |
$sw_favicon == 3; | |
} | |
} | |
if ($sw_favicon == 3 ) { // WebAPIを利用 | |
// サイトアイコン取得(WebAPI) | |
if (isset($this->options['favicon-api'] ) ) { | |
$favicon = preg_replace('/%DOMAIN_URL%/', $domain_url, $this->options['favicon-api'] ); | |
$favicon = preg_replace('/%DOMAIN%/', $domain, $favicon); | |
$favicon = preg_replace('/%URL%/', rawurlencode($url), $favicon); | |
$favicon = '<img class="lkc-favicon" src="'.$favicon.'" alt="" width=16 height=16 />'; | |
} | |
} | |
} | |
// タイトル | |
if (!$title ) { | |
$title = esc_html($url ); // タイトル取得できていなかったらURLをセットする | |
} | |
// パラメータ取得(タイトル・抜粋文) | |
if ($atts['title'] ) { // title パラメータ | |
$title = $atts['title']; | |
$excerpt = null; | |
} | |
if ($atts['excerpt'] ) { // excerpt パラメータ | |
$excerpt = $atts['excerpt']; | |
} | |
// タイトル整形 | |
if ($title ) { | |
$str = $title; | |
$str = strip_tags($str ); // タグの除去 | |
$str = str_replace(array("\r", "\n"), '', $str); // 改行削除 | |
$str = esc_html($str ); // 念のためエスケープ | |
if ($this->options['trim-title'] ) { | |
$str = mb_strimwidth($str, 0, $this->options['trim-title'] , '...' ); | |
} | |
$title = $str; | |
} | |
// 抜粋文整形(抜粋文非表示の場合、空欄にする) | |
if (!$this->options['display-excerpt'] ) { | |
$excerpt = ''; | |
} else { | |
if ($excerpt ) { | |
$str = $excerpt; | |
$str = strip_tags($str ); // タグの除去 | |
$str = preg_replace('/<!--more-->.+/is', '', $str ); // moreタグ以降削除 | |
$str = preg_replace('/\[[^]]*\]/', '', $str ); // ショートコードすべて除去 | |
$str = str_replace(array("\r", "\n"), '', $str ); // 改行削除 | |
$str = esc_html($str ); // 念のためエスケープ | |
if ($this->options['trim-excerpt'] ) { | |
$str = mb_strimwidth($str, 0, $this->options['trim-excerpt'] , '...' ); | |
} | |
$excerpt = $str; | |
} | |
} | |
// サイト名称を使わない場合、ドメイン名で上書き | |
$site_title = null; | |
if ($this->options['use-sitename'] && $site_name ) { | |
$c_site_name = $site_name; | |
if ($this->options['trim-info']) { | |
$str = $site_name; | |
$str = mb_strimwidth($str, 0, $this->options['trim-info'] , '...'); | |
$site_name = $str; | |
} | |
if ($site_name <> $c_site_name ) { | |
$site_title = ' title="'.$c_site_name.'"'; | |
} | |
} else { | |
$site_name = $domain; | |
// 日本語ドメイン対応 | |
if ($this->options['flg-idn'] && function_exists('idn_to_utf8' ) && substr($domain, 0, 4 ) == 'xn--' ) { | |
$site_name = idn_to_utf8($domain ); | |
} | |
} | |
// リンク先URL | |
if ($this->options['flg-unlink'] && array_search($alive_result, array('403','404','410' ) ) ) { | |
// Not Found の時は見え消ししてリンクしない | |
$a_op_all = '<div style="cursor: not-allowed;" title="">'; | |
$a_cl_all = '</div>'; | |
$a_op = ''; | |
$a_cl = ''; | |
$st_op = '<strike>'; | |
$st_cl = '</strike>'; | |
} elseif ($this->options['link-all'] ) { | |
// カード全体をリンク(どこをクリックしても良いのが分かり易い) | |
$a_op_all = '<a class="lkc-link no_icon" href="'.$url.'"'.$target.$rel.'>'; | |
$a_cl_all = '</a>'; | |
$a_op = null; | |
$a_cl = null; | |
$st_op = null; | |
$st_cl = null; | |
} else { | |
// タイトルとかURLとかを個別でリンク(タイトルや抜粋文などの文字を範囲指定をしてコピー等がし易い) | |
$a_op_all = null; | |
$a_cl_all = null; | |
$a_op = '<a class="lkc-link no_icon" href="'.$url.'"'.$target.$rel.'>'; | |
$a_cl = '</a>'; | |
$st_op = null; | |
$st_cl = null; | |
} | |
// ソーシャルカウントの表示 | |
$sns = null; | |
$sns_title = null; | |
$sns_info = null; | |
if ($this->options['sns-position'] ) { | |
// カード全体をリンクにするときは表示のみ | |
if ($this->options['link-all'] ) { | |
if ($this->options['sns-tw'] && $sns_tw > 0 ) { | |
$sns .= ' <div class="lkc-sns-tw">'.$sns_tw.' tweet' .(($sns_tw > 1) ? 's' : '').'</div>'; | |
} | |
if ($this->options['sns-fb'] && $sns_fb > 0 ) { | |
$sns .= ' <div class="lkc-sns-fb">'.$sns_fb.' share' .(($sns_fb > 1) ? 's' : '').'</div>'; | |
} | |
if ($this->options['sns-hb'] && $sns_hb > 0 ) { | |
$sns .= ' <div class="lkc-sns-hb">'.$sns_hb.' user' .(($sns_hb > 1) ? 's' : '').'</div>'; | |
} | |
if ($this->options['sns-po'] && $sns_po > 0 ) { | |
$sns .= ' <div class="lkc-sns-po">'.$sns_po.' pocket'.(($sns_po > 1) ? 's' : '').'</div>'; | |
} | |
} else { | |
// 外部リンクアイコンを表示させるプラグイン対応のため no_icon を付与 | |
if ($this->options['sns-tw'] && $sns_tw > 0 ) { | |
$sns .= ' <a class="lkc-sns-tw no_icon" href="https://twitter.com/search?q=' .preg_replace('/.*\/\/(.*)/', '$1', $url).'&text='.esc_html($title).'" target="_blank">'.$sns_tw.' tweet'.(($sns_tw > 1) ? 's' : '').'</a>'; | |
} | |
if ($this->options['sns-fb'] && $sns_fb > 0 ) { | |
$sns .= ' <a class="lkc-sns-fb no_icon" href="https://www.facebook.com/" target="_blank">'.$sns_fb.' share'.(($sns_fb > 1) ? 's' : '').'</a>'; | |
} | |
if ($this->options['sns-hb'] && $sns_hb > 0 ) { | |
$sns .= ' <a class="lkc-sns-hb no_icon" href="https://b.hatena.ne.jp/entry/s/' .preg_replace('/.*\/\/(.*)/', '$1', $url).'" target="_blank">'.$sns_hb.' user'.(($sns_hb > 1) ? 's' : '').'</a>'; | |
} | |
if ($this->options['sns-po'] && $sns_po > 0 ) { | |
$sns .= ' <a class="lkc-sns-po no_icon" href="https://getpocket.com/" target="_blank">'.$sns_po.' pocket'.(($sns_po > 1) ? 's' : '').'</a>'; | |
} | |
} | |
if ($sns ) { | |
if ($this->options['sns-position'] == '1') { | |
$sns_title = '<div class="lkc-share">'.$sns.'</div>'; | |
} else { | |
$sns_info = ' '.'<div class="lkc-share">'.$sns.'</div>'; | |
} | |
} | |
} | |
// サムネイル | |
if ($thumbnail ) { | |
$thumbnail = '<figure class="lkc-thumbnail">'.$thumbnail.'</figure>'; | |
} | |
// 日本語ドメイン対応 | |
if ($this->options['flg-idn'] && function_exists('idn_to_utf8') && substr($domain, 0, 4 ) == 'xn--') { | |
$url = $scheme.'://'.idn_to_utf8($domain ).$location; | |
} | |
// 続きを読むボタン | |
if ($more && $more_text ) { | |
$moretag = '<div class="lkc-more">'.$a_op.'<div class="lkc-more-text">'.$more_text.'</div>'.$a_cl.'</div>'; | |
} else { | |
$moretag = null; | |
} | |
// リンク先URL | |
$url1 = null; | |
$url2 = null; | |
if ($this->options['display-url'] ) { | |
if ($this->options['display-url'] == '2' ) { | |
$url2 = ' <div class="lkc-url-info"><cite>'.$st_op.$a_op.$url.$st_cl.$a_cl.'</cite></div>'; | |
} else { | |
$url1 = '<div class="lkc-url"><cite>'.$st_op.$a_op.$url.$st_cl.$a_cl.'</cite></div>'; | |
} | |
} | |
// サイト情報 | |
if ($info ) { | |
$added_info = $added_op.$info.$added_cl; | |
} else { | |
$added_info = null; | |
} | |
if ($this->options['display-date'] && $link_type ) { | |
$post_dat = '<div class="lkc-date">'.date('Y.m.d', strtotime($post_date)).'</div>'; | |
} else { | |
$post_date = null; | |
} | |
$domain_info = '<div class="lkc-info">'.$a_op.$favicon.'<div class="lkc-domain"'.$site_title.'>'.$site_name.'</div>'.$added_info.$a_cl.$sns_info.$url2.$post_date.'</div>'; | |
// Google AMPに対応 | |
if ((function_exists('is_amp_endpoint' ) && is_amp_endpoint() ) || $this->amp || ($this->options['flg-amp-url'] && (preg_match('/\/amp\/?$/i', $_SERVER["REQUEST_URI"]) || preg_match('/\?amp=1$/i', $_SERVER["REQUEST_URI"]) ) ) ) { | |
// 簡易タグ作成 | |
$tag = '<table border="1" cellspacing="0" cellpadding="4"><tbody></tr><tr><td>'.$excerpt.'<br>'.$a_op_all.$a_op.$title.$a_cl.$a_cl_all.' - '.$site_name.'</td></tr></tbody></table>'; | |
} else { | |
// HTMLタグ作成 | |
switch (isset($this->options['info-position']) ? $this->options['info-position'] : null) { | |
case '1': | |
$tag = $wrap_op.$a_op_all.'<div class="lkc-card">'.$domain_info.'<div class="lkc-content">'.$a_op.$thumbnail.'<div class="lkc-title"><div class="lkc-title-text">'.$title.'</div>'.$a_cl.$sns_title.'</div>'.$url1.'<div class="lkc-excerpt">'.$excerpt.'</div>'.$moretag.'</div><div class="clear"></div></div>'.$a_cl_all.$wrap_cl; | |
break; | |
case '2': | |
$tag = $wrap_op.$a_op_all.'<div class="lkc-card"><div class="lkc-content">'.$a_op.$thumbnail.'<div class="lkc-title"><div class="lkc-title-text">'.$title.'</div>'.$a_cl.$sns_title.'</div>'.$url1.'<div class="lkc-excerpt">'.$excerpt.'</div>'.$moretag.'</div>'.$domain_info.'<div class="clear"></div></div>'.$a_cl_all.$wrap_cl; | |
break; | |
case '3': | |
$tag = $wrap_op.$a_op_all.'<div class="lkc-card"><div class="lkc-content">'.$a_op.$thumbnail.$domain_info.'<div class="lkc-title"><div class="lkc-title-text">'.$title.'</div>'.$a_cl.$sns_title.$url1.'</div><div class="lkc-excerpt">'.$excerpt.'</div>'.$moretag.'</div><div class="clear"></div></div>'.$a_cl_all.$wrap_cl; | |
break; | |
default: | |
$tag = $wrap_op.$a_op_all.'<div class="lkc-card"><div class="lkc-content">'.$a_op.$thumbnail.'<div class="lkc-title"><div class="lkc-title-text">'.$title.'</div>'.$a_cl.$sns_title.'</div>'.$url1.'<div class="lkc-excerpt">'.$excerpt.'</div>'.$moretag.'</div><div class="clear"></div></div>'.$a_cl_all.$wrap_cl; | |
} | |
} | |
// 引用文扱い | |
if (isset($this->options['blockquote']) ? $this->options['blockquote'] : null == '1') { | |
$tag = '<div class="'.$class_id.'"><blockquote class="lkc-quote">'.$tag.'</blockquote></div>'; | |
} else { | |
$tag = '<div class="'.$class_id.'">'.$tag.'</div>'; | |
} | |
return $tag; | |
} | |
// URLのエンティティ化など(無害化?) | |
private function pz_TrimURL($url = null ) { | |
if ($this->options['debug-time']) { | |
echo '<!-- Pz-LkC [pz_TrimURL]'.PHP_EOL; | |
echo '$url='.html_entity_decode($url ).PHP_EOL; | |
echo '/-->'.PHP_EOL; | |
} | |
if (!$url ) { | |
return $url; | |
} | |
$url = html_entity_decode($url ); | |
$url = preg_replace('/^[\s \'\"‘’“”″]*(.*?)[\s \'\"‘’“”″]*$/u', '\1', $url ); // 色んな打ち間違え対応 | |
$url = esc_url($url ); // プロトコル除外など | |
$url = trim($url ); | |
switch (isset($this->options['trail-slash']) ? $this->options['trail-slash'] : null ) { | |
case '1': // URLがドメイン名だけの場合、最後のスラッシュを除外する | |
$array_url = parse_url($url); | |
if (!isset($array_url['path']) || $array_url['path'] == '/') { | |
$url = rtrim($url, '/'); | |
} | |
break; | |
case '2': // 常に最後のスラッシュを除外する | |
$url = rtrim($url, '/'); | |
break; | |
} | |
if ($this->options['debug-time']) { | |
echo '<!-- Pz-LkC [pz_TrimURL]'.PHP_EOL; | |
echo 'return'.PHP_EOL; | |
echo '$url='.html_entity_decode($url ).PHP_EOL; | |
echo '/-->'.PHP_EOL; | |
} | |
return $url; | |
} | |
// 内部サイト・外部サイトの判断 | |
private function pz_LinkType($url = null ) { | |
if (substr($url, 0, mb_strlen(home_url() ) ) == home_url() ) { | |
if (get_permalink() == $url) { | |
$link_type = 1; // 自ページ | |
} else { | |
$link_type = 2; // 自サイト内 | |
} | |
} else { | |
$link_type = 0; // 外部サイト | |
} | |
// サブディレクトリ型マルチサイト対応 | |
if ($this->options['flg-subdir'] && function_exists('is_multisite') && is_multisite() && function_exists('is_subdomain_install') && !is_subdomain_install() && function_exists('is_main_site') && is_main_site()) { | |
$this_blog_id = get_current_blog_id(); | |
$blog_id = 0; | |
do { | |
$blog_id++; | |
$blog_url = get_site_url($blog_id); | |
if ($blog_url && $blog_id <> $this_blog_id && substr($url, 0, mb_strlen($blog_url) ) == $blog_url ) { | |
// ドメイン名 | |
if (preg_match('/https?:\/\/(.*)\//i', $blog_url.'/',$m)) { | |
$domain_url = $m[0]; | |
$domain = $m[1]; | |
} else { | |
$domain_url = null; | |
$domain = null; | |
} | |
$link_type = 0; // 外部サイト | |
} | |
} while ($blog_url); | |
} | |
if ($this->options['debug-time']) { | |
echo '<!-- Pz-LkC [TYPE='.$link_type.'] /-->'.PHP_EOL; | |
} | |
return $link_type; | |
} | |
// 相対パスをURLにする | |
private function pz_RelToURL( $base_url = '', $rel_path = '' ) { | |
if (preg_match('/^https?\:\/\//', $rel_path ) ) { // 絶対パスだった場合 | |
return $rel_path; | |
} elseif (substr($rel_path, 0, 2) == '//' ) { // 絶対パスだった場合(スキーム省略) | |
return $rel_path; | |
} | |
$parse = parse_url($base_url ); | |
if (substr($rel_path, 0, 1) == '/' ) { // ドキュメントルート指定 | |
return $parse['scheme'].'://'.$parse ['host'].$rel_path; | |
} | |
return $parse['scheme'].'://'.$parse['host'].dirname($parse['path'] ).'/'.$rel_path; | |
} | |
// ソーシャルカウント取得 | |
private function pz_RenewSNSCount($data ) { | |
if (!isset($this->options['sns-position']) || $this->options['sns-position'] == '') { | |
return null; | |
} | |
if (!isset($data) || !is_array($data)) { | |
return null; | |
} | |
$data = $this->pz_GetCache($data); | |
if (!isset($data) || !is_array($data)) { | |
return null; | |
} | |
// ソーシャルカウント | |
$sns_renew = false; | |
$update_cnt = false; | |
// タイムオーバー | |
$opt = array( 'timeout' => 30 ); | |
// 保存期間満了でソーシャルカウントをリセット | |
if ($this->now > $data['sns_nexttime'] && $data['result_code'] <= 200 ) { | |
$sns_renew = true; | |
} | |
// エンコードURL | |
$url_raw = rawurlencode($data['url']); | |
// Twitter Digitminimiのcount.jsoonを使用 | |
if (isset($this->options['sns-tw']) && !is_null($this->options['sns-tw'])) { | |
$count_before = isset($data['sns_twitter']) ? $data['sns_twitter'] : -1; | |
if ($sns_renew || $count_before < 0) { | |
$result = wp_remote_get( 'https://jsoon.digitiminimi.com/twitter/count.json?url=' .$url_raw, $opt ); | |
if (isset($result) && !is_wp_error($result) && $result['response']['code'] == 200) { | |
$json = json_decode($result['body']); | |
$count = intval($json->count); | |
if ($count > $count_before) { | |
$data['sns_twitter'] = $count; | |
$update_cnt = true; | |
} | |
} | |
} | |
} | |
//if (isset($this->options['sns-fb']) && !is_null($this->options['sns-fb'])) { | |
// $count_before = intval(isset($data['sns_facebook']) ? $data['sns_facebook'] : -1); | |
// if ($sns_renew || $count_before < 0) { | |
// $result = wp_remote_get( 'https://graph.facebook.com?fields=og_object{engagement}&id=' .$url_raw, $opt ); | |
// if (isset($result) && !is_wp_error($result) && $result['response']['code'] == 200) { | |
// $json = json_decode($result['body']); | |
// $count = intval($json->{'og_object'}->{'engagement'}->{'count'}); | |
// if ($count > $count_before) { | |
// $data['sns_facebook'] = $count; | |
// $update_cnt = true; | |
// } | |
// } | |
// } | |
//} | |
// はてなブックマーク | |
if (isset($this->options['sns-hb']) && !is_null($this->options['sns-hb'])) { | |
$count_before = isset($data['sns_hatena']) ? $data['sns_hatena'] : -1; | |
if ($sns_renew || $count_before < 0) { | |
$result = wp_remote_get( 'http://api.b.st-hatena.com/entry.count?url=' .$url_raw, $opt ); | |
if (isset($result) && !is_wp_error($result) && $result['response']['code'] == 200) { | |
$count = intval($result['body']); | |
if ($count > $count_before) { | |
$data['sns_hatena'] = $count; | |
$update_cnt = true; | |
} | |
} | |
} | |
} | |
if (isset($this->options['sns-po']) && !is_null($this->options['sns-po'])) { | |
$count_before = isset($data['sns_pocket']) ? $data['sns_pocket'] : -1; | |
if ($sns_renew || $count_before < 0) { | |
$result = wp_remote_get( 'https://widgets.getpocket.com/api/saves?url=' .$url_raw, $opt ); | |
if (isset($result) && !is_wp_error($result) && $result['response']['code'] == 200) { | |
$json = json_decode($result['body']); | |
$count = intval($json->saves); | |
if ($count > $count_before) { | |
$data['sns_pocket'] = $count; | |
$update_cnt = true; | |
} | |
} | |
} | |
} | |
// 登録してから一週間までは毎日、それ以降は週一回更新(取得が固まらないようにランダム時間付与) | |
if ($update_cnt || ($this->now - strtotime($data['regist']) < WEEK_IN_SECONDS)) { | |
$sns_nexttime = $this->now + DAY_IN_SECONDS + rand(0, DAY_IN_SECONDS); // 1day + 0-24h | |
} else { | |
$sns_nexttime = $this->now + WEEK_IN_SECONDS + rand(0, DAY_IN_SECONDS); // 7days + 0-24h | |
} | |
// MINUTE_IN_SECONDS = 60 | |
// HOUR_IN_SECONDS = 60 * MINUTE_IN_SECONDS = 3600 | |
// DAY_IN_SECONDS = 24 * HOUR_IN_SECONDS = 86400 | |
// WEEK_IN_SECONDS = 7 * DAY_IN_SECONDS = 604800 | |
// YEAR_IN_SECONDS = 365 * DAY_IN_SECONDS | |
global $wpdb; | |
$wpdb->update( | |
$this->db_name, | |
array( | |
'sns_twitter' => $data['sns_twitter'], | |
'sns_facebook' => $data['sns_facebook'], | |
'sns_hatena' => $data['sns_hatena'], | |
'sns_pocket' => $data['sns_pocket'], | |
'sns_time' => $this->now, | |
'sns_nexttime' => $sns_nexttime, | |
'uptime' => $this->now | |
), | |
array( | |
'id' => $data['id'] | |
) | |
); | |
return $data; | |
} | |
// キャッシュデータを取得 | |
private function pz_GetCache($data ) { | |
if (!isset($data) || !is_array($data)) { | |
return null; | |
} | |
global $wpdb; | |
if (!empty($data['url'])) { | |
$url = $data['url']; | |
$data = $wpdb->get_row($wpdb->prepare("SELECT * FROM $this->db_name WHERE url=%s", $url)); | |
} elseif (isset($data['id']) && !is_null($data['id'])) { | |
$data_id = intval($data['id']); | |
$data = $wpdb->get_row($wpdb->prepare("SELECT * FROM $this->db_name WHERE id=%d", $data_id)); | |
} else { | |
return null; | |
} | |
if ($wpdb->last_error <> '') { // DBエラーのとき、初期化する | |
$this->activate(); | |
} | |
if (is_wp_error($data)) { | |
return null; | |
} | |
return (array) $data; // Arrayに直して返す | |
} | |
// キャッシュデータを保存 | |
private function pz_SetCache($data ) { | |
global $wpdb; | |
if (!isset($data) || !is_array($data)) { | |
return null; | |
} | |
if (!isset($data['url']) || is_null($data['url']) || $data['result_code'] < 100) { | |
return null; | |
} | |
// リンク先URL | |
$url = $this->pz_TrimURL($data['url']); | |
$data['url'] = $url; | |
// URLからキーの生成 | |
if (!isset($data['url_key']) || is_null($data['url_key']) || $data['url_key'] == '' ) { | |
$data['url_key'] = hash( 'sha256', esc_url( $url ), true); | |
} | |
// 登録時情報 | |
if (!isset($data['regist_result']) || !$data['regist_result']) { | |
$data['regist_title'] = $data['title']; | |
$data['regist_excerpt'] = $data['excerpt']; | |
$data['regist_charset'] = $data['charset']; | |
$data['regist_result'] = $data['result_code']; | |
$data['regist_time'] = $this->now; | |
} | |
// 最終更新日時 | |
$data['uptime'] = $this->now; | |
// DB更新 | |
if ( isset($data['id']) ) { | |
$result = $wpdb->update( | |
$this->db_name, | |
$data, | |
array( | |
'id' => $data['id'] | |
) | |
); | |
} else { | |
$result = $wpdb->update( | |
$this->db_name, | |
$data, | |
array( | |
'url_key' => $data['url_key'] | |
) | |
); | |
} | |
// DB更新失敗の場合、挿入 | |
if (!$result) { | |
// 登録日 | |
$data['regist'] = $this->now_mysql; | |
// 新規の場合、IDをクリア | |
unset($data['id']); | |
$result = $wpdb->insert( | |
$this->db_name, | |
$data | |
); | |
// DB挿入失敗の場合、日本語項目(サイト名)をクリアして挿入 | |
if (!$result) { | |
unset($data['site_name']); | |
$result = $wpdb->insert( | |
$this->db_name, | |
$data | |
); | |
// DB挿入失敗の場合、日本語項目(概要文)をクリアして挿入 | |
if (!$result) { | |
unset($data['excerpt']); | |
$result = $wpdb->insert( | |
$this->db_name, | |
$data | |
); | |
// DB挿入失敗の場合、日本語項目(タイトル)をクリアして挿入 | |
if (!$result) { | |
unset($data['title']); | |
$result = $wpdb->insert( | |
$this->db_name, | |
$data | |
); | |
// DB挿入失敗の場合、諦める | |
if (!$result) { | |
return $data; | |
} | |
} | |
} | |
} | |
} | |
// 登録された内容を読み直す | |
return $this->pz_GetCache($data); | |
} | |
// キャッシュデータを削除 | |
private function pz_DelCache($data ) { | |
global $wpdb; | |
if (!isset($data) || !is_array($data)) { | |
return null; | |
} | |
if (isset($data['id']) && !is_null($data['id'])) { | |
$data_id = intval($data['id']); | |
$result = $wpdb->delete($this->db_name, array('id' => $data_id), array('%d') ); | |
return $result; | |
} elseif (isset($data['url']) && !is_null($data['url'])) { | |
$url = $this->pz_TrimURL($data['url']); | |
$result = $wpdb->delete($this->db_name, array('url' => $url), array('%s') ); | |
return $result; | |
} | |
return null; | |
} | |
// サイト内取得 | |
private function pz_GetPost( $data ) { | |
// サイト名取得 | |
$site_name = get_bloginfo('name'); | |
// ドメイン名 | |
if (preg_match('/https?:\/\/(.*)\//i', home_url().'/',$m)) { | |
$domain_url = $m[0]; | |
$domain = $m[1]; | |
} else { | |
$domain_url = null; | |
$domain = null; | |
} | |
// サイトアイコン | |
if (function_exists('has_site_icon') && has_site_icon()) { | |
$favicon = get_site_icon_url(16, '', 0); | |
} else { | |
$favicon = null; | |
} | |
$title = null; | |
$excerpt = null; | |
$thumbnail = null; | |
// 記事内容 | |
$url = $data['url']; | |
$post_id = url_to_postid($url ); // 記事IDを取得 | |
if ($this->options['debug-time']) { | |
echo '<!-- Pz-LkC [PID='.$post_id.'] /-->'.PHP_EOL; | |
} | |
if ( !$post_id && isset($this->options['flg-get-pid']) ? true : false) { | |
$url = $this->Pz_GetRedirURL( $data ); // 本当の記事URLを取得 | |
$post_id = url_to_postid($url ); // 記事IDを取得 | |
if ($this->options['debug-time']) { | |
echo '<!-- Pz-LkC [PID='.$post_id.'(REDIR)] /-->'.PHP_EOL; | |
} | |
} | |
if ( $post_id ) { | |
$result_code = 200; // 外部取得と同じコードをセット | |
$post = get_post($post_id); // 記事情報 | |
if ( $this->options['in-get'] == '1') { | |
$title = $post->post_title; // 記事タイトル | |
$excerpt = $post->post_excerpt; // 抜粋文優先 | |
if ($excerpt == '') { | |
$excerpt = $post->post_content; // 抜粋文が無かったら記事 | |
} | |
} else { | |
$title = $post->post_title; // 記事タイトル | |
$excerpt = $post->post_content; // 記事内容から抜粋 | |
} | |
$post_date = $post->post_date; | |
$thumbnail_id = get_post_thumbnail_id( $post_id ); // サムネイル | |
if ($this->options['debug-time']) { | |
echo '<!-- Pz-LkC [TID='.$thumbnail_id.'] /-->'.PHP_EOL; | |
} | |
$attach = wp_get_attachment_image_src( $thumbnail_id, 'thumbnail', true ); | |
if (isset($attach) && count($attach) > 3 && isset($attach[0])) { | |
$thumbnail = $attach[0]; | |
if (preg_match('/.*(\/\/.*)/', $thumbnail, $m)) { // スキームを外す | |
$thumbnail = $m[1]; | |
} | |
} | |
} else { | |
$title = get_bloginfo('name'); | |
$excerpt = get_bloginfo('description'); | |
$site_name = get_bloginfo('name'); | |
$thumbnail = ''; | |
$result_code = '404'; | |
// カテゴリ ページの処理 | |
$cat_dir = get_option('category_base'); | |
$cat_url = home_url().'/'.($cat_dir ? $cat_dir : 'category').'/'; | |
$cat_len = mb_strlen($cat_url ); | |
if (substr($url, 0, $cat_len ) == $cat_url ) { | |
$cat_slug = substr($url, $cat_len ); | |
$cat_data = get_category_by_slug($cat_slug ); | |
$cat_count = ($cat_data->count - 0); | |
$title = __('Category', $this->text_domain ).' '.__('‘', $this->text_domain ).$cat_data->name.__('’', $this->text_domain ); | |
$excerpt = __('(', $this->text_domain ).__('Count', $this->text_domain ).':'.($cat_data->count - 0).__(')', $this->text_domain ).' '.$cat_data->description; | |
if (isset($cat_data->slug)) { | |
$result_code = '200'; | |
} | |
} else { | |
// タグ ページの処理 | |
$cat_dir = get_option('tag_base'); | |
$cat_url = home_url().'/'.($cat_dir ? $cat_dir : 'tag').'/'; | |
$cat_len = mb_strlen($cat_url ); | |
if (substr($url, 0, $cat_len ) == $cat_url ) { | |
$cat_slug = substr($url, $cat_len ); | |
$cat_data = get_tags( array( 'slug' => $cat_slug ) ); | |
$title = __('Tag', $this->text_domain ).' '.__('‘', $this->text_domain ).$cat_data[0]->name.__('’', $this->text_domain ); | |
$excerpt = __('(', $this->text_domain ).__('Count', $this->text_domain ).':'.($cat_data[0]->count - 0).__(')', $this->text_domain ).' '.$cat_data[0]->description; | |
if (isset($cat_data[0]->slug)) { | |
$result_code = '200'; | |
} | |
} else { | |
if ( !$post_id && isset($this->options['flg-get-pid']) ? true : false) { | |
$data = $this->Pz_GetCURL($data ); // 外部サイトとして読み込み | |
return $data; | |
} | |
} | |
} | |
} | |
// タイトル整形 | |
if (isset($title)) { | |
$str = $title; | |
$str = strip_tags($str); // タグの除去 | |
$str = str_replace(array("\r", "\n"), '', $str); // 改行削除 | |
$str = esc_html($str); // 念のためエスケープ | |
$str = mb_strimwidth($str, 0, 200, '...'); // 保管用のタイトルは200文字で切る | |
$title = $str; | |
} | |
// 抜粋文整形 | |
if (isset($excerpt)) { | |
$str = $excerpt; | |
$str = strip_tags($str); // タグの除去 | |
$str = preg_replace('/<!--more-->.+/is', '', $str); // moreタグ以降削除 | |
$str = preg_replace('/\[[^]]*\]/', '', $str); // ショートコードすべて除去 | |
$str = str_replace(array("\r", "\n"), '', $str); // 改行削除 | |
$str = esc_html($str); // 念のためエスケープ | |
$str = mb_strimwidth($str, 0, 500, '...'); // 保管用の記事内容は500文字で切る | |
$excerpt = $str; | |
} | |
// URLパース(ドメイン名などを抽出) | |
$url_m = parse_url($url ); | |
$scheme = isset($url_m['scheme']) ? $url_m['scheme'] : null; // スキーム | |
$domain = isset($url_m['host']) ? $url_m['host'] : null; // ドメイン名 | |
$domain_url = isset($url_m['host']) ? $scheme.'://'.$url_m['host'] : null; // ドメインURL | |
$location = isset($url_m['path']) ? $url_m['path'] : null; // ドメイン名以降 | |
// データセット | |
if (isset($data['title']) && $data['title'] == $title ) { | |
$before['mod_title'] = 0; | |
} else { | |
$before['mod_title'] = 1; | |
} | |
if (isset($data['excerpt']) && $data['excerpt'] == $excerpt ) { | |
$before['mod_excerpt'] = 0; | |
} else { | |
$before['mod_excerpt'] = 1; | |
} | |
if (!isset($data['use_post_id1'])) { | |
$data['use_post_id1'] = get_the_ID(); | |
} | |
$data['scheme'] = $scheme; | |
$data['domain'] = $domain; | |
$data['location'] = $location; | |
$data['site_name'] = $site_name; | |
$data['title'] = $title; | |
$data['excerpt'] = $excerpt; | |
$data['post_date'] = $post_date; | |
$data['thumbnail'] = $thumbnail; | |
$data['favicon'] = $favicon; | |
$data['charset'] = 'UTF-8'; | |
$data['result_code'] = $result_code; | |
$data['alive_result'] = $result_code; | |
$data['favicon'] = $favicon; | |
return $data; | |
} | |
// リダイレクト先URL取得 | |
private function pz_GetRedirURL( $data ) { | |
$url = $data['url']; | |
if ( function_exists( 'curl_init' ) ) { // cURLを使用する | |
$result_code = 0; | |
$ch = curl_init($url); | |
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true ); // データで取得 | |
curl_setopt( $ch, CURLOPT_NOBODY, true ); // ヘッダのみ取得 | |
curl_setopt( $ch, CURLOPT_TIMEOUT, 120 ); // タイムアウト | |
curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, true ); // リダイレクトを処理する | |
curl_setopt( $ch, CURLOPT_MAXREDIRS, 5 ); // リダイレクトを処理する階層 | |
$html = curl_exec($ch); | |
$errno = intval( curl_errno( $ch ) ); // cURL実行 | |
if ( $errno ) { | |
$result_code = $errno; | |
$error = true; | |
} else { | |
$header = curl_getinfo($ch); | |
$result_code = $header['http_code']; // HTTPステータス | |
$error = false; | |
$url = $header['url']; | |
} | |
curl_close($ch); | |
} | |
return $url; | |
} | |
// 外部サイト取得 | |
private function pz_GetCURL($data ) { | |
$url = $this->pz_TrimURL( $data['url'] ); | |
if (!isset( $url ) || $url == '') { | |
return null; | |
} | |
// リンク先サイト取得 | |
$html = null; | |
$error = true; | |
$domain = null; | |
$site_name = null; | |
$title = null; | |
$excerpt = null; | |
$charset = null; | |
$result_code = null; | |
// URLパース(ドメイン名などを抽出) | |
$url_m = parse_url($url ); | |
$scheme = isset($url_m['scheme']) ? $url_m['scheme'] : null; // スキーム | |
$domain = isset($url_m['host']) ? $url_m['host'] : null; // ドメイン名 | |
$domain_url = isset($url_m['host']) ? $scheme.'://'.$url_m['host'] : null; // ドメインURL | |
$location = isset($url_m['path']) ? $url_m['path'] : null; // ドメイン名以降 | |
if ( function_exists('curl_init' ) ) { // cURLを使用する | |
$result_code = 0; | |
$ch = curl_init($url); | |
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true ); // データで取得 | |
curl_setopt( $ch, CURLOPT_TIMEOUT, 8 ); // タイムアウト | |
if (isset($this->options['flg-referer']) ? true : false) { | |
curl_setopt( $ch, CURLOPT_REFERER, get_permalink() ); // リファラ | |
} | |
if (isset($this->options['flg-agent']) ? true : false) { | |
curl_setopt( $ch, CURLOPT_USERAGENT, $this->options['user-agent'] ); // ユーザーエージェントにPz-LinkCard-Crawlerを使う | |
} else { | |
curl_setopt( $ch, CURLOPT_USERAGENT, esc_html( $_SERVER['HTTP_USER_AGENT'] ) ); // アクセス者のユーザーエージェントを使う | |
} | |
if (isset($this->options['flg-redir']) ? true : false) { | |
curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, true ); // リダイレクトを処理する | |
curl_setopt( $ch, CURLOPT_MAXREDIRS, 8 ); // リダイレクトを処理する階層 | |
curl_setopt( $ch, CURLOPT_AUTOREFERER, true ); // リダイレクト用リファラを自動セット | |
} else { | |
curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, false ); // リダイレクトを処理しない | |
} | |
curl_setopt( $ch, CURLOPT_COOKIESESSION, true ); // セッションCOOKIEを使用する | |
curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, (isset($this->options['flg-ssl']) ? false : true) ); // SSL検証 | |
$html = curl_exec($ch); | |
$errno = intval( curl_errno( $ch ) ); // cURL実行 | |
if ( $errno ) { | |
$html = ''; // cURLエラー | |
$result_code = $errno; | |
$error = true; | |
} else { | |
$header = curl_getinfo($ch); | |
$result_code = $header['http_code']; // HTTPステータス | |
$error = false; | |
} | |
curl_close($ch); | |
} else { // cURLが使用できない場合 | |
$result = wp_remote_get( $url ); //wp_remote_get実行 | |
if ( is_wp_error( $result ) ) { | |
$html = ''; | |
$result_code = -1; // wp_remote_getエラー | |
$error = true; | |
} else { | |
$html = $result['body']; | |
$result_code = $result['response']['code']; // HTTPステータス | |
$error = false; | |
} | |
} | |
// 文字コード判定 | |
$charset = null; | |
if ($html <> '') { | |
if (preg_match('/charset\s*=\s*"*([^>\/\s"]*).*<\/head/si', $html, $m)) { | |
$m[1] = trim(trim($m[1]), '\'\"'); | |
$charset = $m[1]; | |
} else { | |
foreach(array('UTF-8','SJIS','EUC-JP','eucJP-win','ASCII','JIS','SJIS-win') as $c_charset) { | |
// 文字コード変換してみて内容が変わらないものを文字セットと判断する | |
if (mb_convert_encoding($html, $this->charset, $c_charset) == $html) { | |
$charset = $c_charset; | |
break; | |
} | |
} | |
} | |
if (is_null($charset)) { | |
$charset = mb_detect_encoding($html, 'ASCII,JIS,UTF-7,EUC-JP,SJIS,UTF-8'); | |
$html = mb_convert_encoding($html, $this->charset, 'ASCII,JIS,UTF-7,EUC-JP,SJIS,UTF-8'); | |
} elseif ($this->charset <> $charset) { | |
$html = mb_convert_encoding($html, $this->charset, $charset); | |
} | |
// HEADタグ(METAタグ解析) | |
$head = null; | |
$tags = null; | |
if (preg_match('/<\s*head[^>]*>(.*)<\s*\/head\s*>/si', $html, $m)) { | |
$head = $m[1]; | |
$tags = $this->pz_GetMeta($head); | |
} | |
// タイトル | |
if (isset( $tags['og:title'] ) && $tags['og:title'] ) { | |
$title = $tags['og:title'] ; | |
} elseif (isset( $tags['twitter:title'] ) && $tags['twitter:title'] ) { | |
$title = $tags['twitter:title'] ; | |
} elseif (isset( $tags['title'] ) && $tags['title'] ) { | |
$title = $tags['title'] ; | |
} | |
// 抜粋文・概要文 | |
if (isset( $tags['og:description'] ) && $tags['og:description'] ) { | |
$excerpt = $tags['og:description'] ; | |
} elseif (isset( $tags['twitter:description'] ) && $tags['twitter:description'] ) { | |
$excerpt = $tags['twitter:description'] ; | |
} elseif (isset( $tags['description'] ) && $tags['description'] ) { | |
$excerpt = $tags['description'] ; | |
} | |
// OGPから画像URL取得 | |
if (isset( $tags['og:image'] ) && $tags['og:image'] ) { | |
$thumbnail_url = $tags['og:image'] ; | |
} elseif (isset( $tags['twitter:image'] ) && $tags['twitter:image'] ) { | |
$thumbnail_url = $tags['twitter:image'] ; | |
} else { | |
$thumbnail_url = ''; | |
} | |
if ($thumbnail_url && !preg_match('/^https*:\/\//', $thumbnail_url, $m) ) { | |
$thumbnail_url = $this->pz_RelToURL($url, $thumbnail_url); | |
} | |
// OGPからサイトアイコンURL取得 | |
if (isset( $tags['icon'] ) && $tags['icon'] ) { | |
$favicon_url = $tags['icon'] ; | |
} elseif (isset( $tags['shortcut icon'] ) && $tags['shortcut icon'] ) { | |
$favicon_url = $tags['shortcut icon'] ; | |
} elseif (isset( $tags['apple-touch-icon'] ) && $tags['apple-touch-icon']) { | |
$favicon_url = $tags['apple-touch-icon'] ; | |
} else { | |
$favicon_url = ''; | |
} | |
if ($favicon_url && !preg_match('/^https*:\/\//', $favicon_url, $m) ) { | |
$favicon_url = $this->pz_RelToURL($url, $favicon_url); | |
} | |
// サイト名 | |
if (isset( $tags['og:site_name'] ) && $tags['og:site_name'] ) { | |
$site_name = $tags['og:site_name'] ; | |
} | |
// タイトル整形 | |
if (isset($title)) { | |
$str = $title; | |
$str = strip_tags($str); // タグの除去 | |
$str = str_replace(array("\r", "\n"), '', $str); // 改行削除 | |
$str = esc_html($str); // 念のためエスケープ | |
$str = mb_strimwidth($str, 0, 200, '...'); // 保管用のタイトルは200文字で切る | |
$title = $str; | |
} | |
// 抜粋文整形 | |
if (isset($excerpt)) { | |
$str = $excerpt; | |
$str = strip_tags($str); // タグの除去 | |
$str = str_replace(array("\r", "\n"), '', $str); // 改行削除 | |
$str = esc_html($str); // 念のためエスケープ | |
$str = mb_strimwidth($str, 0, 500, '...'); // 保管用の記事内容は500文字で切る | |
$excerpt = $str; | |
} | |
// データセット | |
if (isset($data_id) && !is_null($data_id)) { | |
$data['id'] = $data_id; | |
} | |
if (isset($url_key) && !is_null($url_key)) { | |
$data['url_key'] = $url_key; | |
} | |
$data['site_name'] = $site_name; | |
$data['title'] = $title; | |
$data['excerpt'] = $excerpt; | |
$data['mod_title'] = 0; | |
$data['mod_excerpt'] = 0; | |
$data['charset'] = $charset; | |
} | |
$data['url'] = $url; | |
$data['thumbnail'] = ( isset($thumbnail_url) ? $thumbnail_url : null ); | |
$data['result_code'] = $result_code; | |
$data['alive_result'] = $result_code; | |
$data['scheme'] = $scheme; | |
$data['domain'] = $domain; | |
$data['location'] = $location; | |
$data['favicon'] = ( isset($favicon_url) ? $favicon_url : null ); | |
if (!isset($data['use_post_id1']) || !$data['use_post_id1']) { | |
$data['use_post_id1'] = get_the_ID(); | |
} | |
$data['sns_twitter'] = (isset( $data['sns_twitter'] ) ? $data['sns_twitter'] : -1 ); | |
$data['sns_facebook'] = (isset( $data['sns_facebook'] ) ? $data['sns_facebook'] : -1 ); | |
$data['sns_hatena'] = (isset( $data['sns_hatena'] ) ? $data['sns_hatena'] : -1 ); | |
$data['sns_nexttime'] = (isset( $data['sns_nexttime'] ) ? $data['sns_nexttime'] : 0 ); | |
$data['uptime'] = $this->now; | |
$data['alive_time'] = $this->now; | |
$data['alive_result'] = $result_code; | |
return $data; | |
} | |
// TITLEとMETAタグを分解 | |
private function pz_GetMeta($html, $tags = null, $clear = false ) { | |
if ($clear == true || !isset($tags)) { | |
$tags = null; | |
$tags = array('none' => 'none'); | |
} | |
// TITLEタグ | |
if (preg_match('/<\s*title\s*[^>]*>\s*([^<]*)\s*<\s*\/title\s*[^>]*>/si', $html, $m)) { | |
$tags['title'] = esc_html($m[1]); | |
} | |
// metaタグ パース | |
$match = null; | |
preg_match_all('/<\s*meta\s(?=[^>]*?\b(?:name|property)\s*=\s*(?|"\s*([^"]*?)\s*"|\'\s*([^\']*?)\s*\'|([^"\'>]*?)(?=\s*\/?\s*>|\s\w+\s*=)))[^>]*?\bcontent\s*=\s*(?|"\s*([^"]*?)\s*"|\'\s*([^\']*?)\s*\'|([^"\'>]*?)(?=\s*\/?\s*>|\s\w+\s*=))[^>]*>/is', $html, $match); | |
if (isset($match) && is_array($match) && count($match) == 3 && count($match[1]) > 0) { | |
foreach ($match[1] as &$m) { | |
$m = strtolower($m); | |
} | |
unset($m); | |
$tags += array_combine($match[1], $match[2]); | |
} | |
// linkタグ パース | |
$match = null; | |
preg_match_all('/<\s*link\s(?=[^>]*?\brel\s*=\s*(?|"\s*([^"]*?)\s*"|\'\s*([^\']*?)\s*\'|([^"\'>]*?)(?=\s*\/?\s*>|\s\w+\s*=)))[^>]*?\bhref\s*=\s*(?|"\s*([^"]*?)\s*"|\'\s*([^\']*?)\s*\'|([^"\'>]*?)(?=\s*\/?\s*>|\s\w+\s*=))[^>]*>/is', $html, $match); | |
if (isset($match) && is_array($match) && count($match) == 3 && count($match[1]) > 0) { | |
foreach ($match[1] as &$m) { | |
$m = strtolower($m); | |
} | |
unset($m); | |
$tags += array_combine($match[1], $match[2]); | |
} | |
return $tags; | |
} | |
// サムネイル取得(外部リンクOGP画像取得) | |
private function pz_GetThumbnail($url, $force = false ) { | |
if (!isset($url) || $url == '' || $url == 'https://s0.wp.com/i/blank.jpg') { | |
return null; | |
} | |
$file_dir = $this->options['thumbnail-dir']; // サムネイルのディレクトリ | |
$file_dir_url = $this->options['thumbnail-url']; // サムネイルのディレクトリURL | |
if (!$file_dir || !$file_dir_url) { | |
return null; | |
} | |
$file_name = bin2hex(hash('sha256', esc_url( $url ), true)); // ファイル名(URLをハッシュしてファイル名にする) | |
$file_ext = '.jpeg'; // 拡張子 | |
$file_path_old = $file_dir.$file_name; // ファイルのフルパス | |
$file_path_jpeg = $file_dir.$file_name.$file_ext; // ファイルのフルパス | |
$file_url = $file_dir_url.$file_name.$file_ext; // 画像URL | |
if (!$force) { | |
if (file_exists ($file_path_jpeg)) { // ファイルが見つかった | |
if (filesize($file_path_jpeg) < 34) { | |
return null; | |
} | |
return $file_url; | |
} | |
if (file_exists ($file_path_old)) { // ファイルが見つかった(拡張子なし) | |
rename ($file_path_old, $file_path_jpeg); // リネーム | |
if (filesize($file_path_jpeg) < 34) { | |
return null; | |
} | |
return $file_url; | |
} | |
} | |
// cURLで画像取得 | |
$ch=curl_init(); | |
curl_setopt($ch, CURLOPT_URL, $url); | |
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); | |
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false); | |
curl_setopt($ch, CURLOPT_TIMEOUT, 10); | |
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 3); | |
$result=curl_exec($ch); | |
curl_close($ch); | |
if (!$result) { | |
touch($file_path_jpeg); // 空ファイル作成 | |
return null; | |
} | |
// 画像生成 | |
$image = imagecreatefromstring($result); // 画像読み込み | |
$image_width = imagesx($image); | |
$image_height = imagesy($image); | |
if ($image_width < 8 || $image_height < 8) { // 8x8未満は画像ではないと見なす | |
touch($file_path_jpeg); // 空ファイル作成 | |
return null; | |
} | |
$new_size = $this->options['cache-image-size']; // サムネイル画像サイズ | |
if ($new_size < $this->defaults['cache-image-size']) { // 小さすぎたらデフォルト値を採用 | |
$new_size = $this->defaults['cache-image-size']; | |
} | |
$new_width = $new_size; // 幅 | |
$new_height = $new_size; // 高さ | |
if ($image_width <> $image_height) { // 正方形でない | |
if ($image_width > $image_height) { // 幅の方が大きい | |
$new_height = $image_height * ( $new_width / $image_width ); // 幅に合わせる | |
} else { // 高さの方が大きい | |
$new_width = $image_width * ( $new_height / $image_height ); // 高さに合わせる | |
} | |
} | |
$new_width = intval($new_width); | |
$new_height = intval($new_height); | |
if ($new_width <= 1 || $new_height <= 1) { | |
touch($file_path_jpeg); // 空ファイル作成 | |
return null; | |
} | |
$image_p = imagecreatetruecolor($new_width, $new_height); // パレットを用意 | |
if (!$image_p) { | |
touch($file_path_jpeg); // 空ファイル作成 | |
return null; | |
} | |
imagecopyresampled($image_p, $image, 0, 0, 0, 0, $new_width, $new_height, $image_width, $image_height); // サイズ変更してコピー | |
imagejpeg($image_p, $file_path_jpeg); // JPEGで保存 | |
return $file_url; // 画像URLを返す | |
} | |
// 管理画面のスタイルシート、スクリプト設定 | |
public function enqueue_admin($hook ) { | |
// カラーピッカー用のスタイルシート、スクリプト | |
wp_enqueue_script ('pz-linkcard-colorpicker', plugins_url('js/color-picker.js', __FILE__), array('wp-color-picker'), false, true); | |
wp_enqueue_script ('wp-color-picker'); | |
wp_enqueue_style ('wp-color-picker'); | |
// 設定画面用のスタイルシート、スクリプト | |
wp_enqueue_script ('pz-linkcard-admin', plugins_url('js/admin-settings.js', __FILE__), array('jquery'), false, true); | |
wp_enqueue_style ('pz-linkcard-admin', plugin_dir_url(__FILE__).'css/admin.css', array(), $this->options['plugin-version']); | |
} | |
// 管理画面時の設定(フッター) | |
public function add_footer() { | |
// テキスト エディタ用のクイックタグ | |
if ($this->options['flg-edit-qtag']) { | |
if (wp_script_is('quicktags') ) { | |
echo '<script>QTags.addButton(\'pz-lkc\',\''.__('Linkcard', $this->text_domain ).'\',\'['.$this->options['code1'].' url="\',\'"]\',\'\',\''.__('Make Linkcard', $this->text_domain ).'\');</script>'; | |
} | |
} | |
// ビジュアル エディタ用の挿入ダイアログ | |
require('lib/pz-linkcard-modal.php'); | |
} | |
// 管理画面時の注意書き設定 | |
public function add_notices() { | |
if ($this->options['flg-invalid']) { | |
if (!$this->options['flg-invalid-hide']) { | |
echo '<div class="error"><p><strong>'.$this->slug.': '.__('Invalid URL parameter in ', $this->text_domain).'<a href="'.$this->options['invalid-url'].'#lkc-error" target="_blank">'.$this->options['invalid-url'].'</a></strong><br>'.__('*', $this->text_domain).' '.__('You can cancel this message from <a href="./options-general.php?page=pz-linkcard-settings">the setting screen</a>.', $this->text_domain).'</p></div>'; | |
} | |
} | |
} | |
// 管理画面時のスタイルシート、スクリプト設定 | |
public function add_mce_button($buttons ) { | |
if ($this->options['flg-edit-insert']) { | |
$buttons[] = 'pz_linkcard_insert_shortcode'; | |
} | |
return $buttons; | |
} | |
public function add_mce_plugin($plugins ) { | |
if ($this->options['flg-edit-insert']) { | |
$plugins[ "pz_linkcard_tinymce" ] = $this->plugin_dir_url.'js/mce-button.js'; | |
} | |
return $plugins; | |
} | |
// 通常時のスタイルシート | |
public function enqueue($hook ) { | |
$this->amp = null; | |
$css_version = $this->options['plugin-version'].'.'.$this->options['css-count']; | |
wp_enqueue_style ('pz-linkcard', $this->options['css-url'], array(), $css_version); | |
if ($this->options['css-url-add']) { | |
wp_enqueue_style('pz-linkcard-add', $this->options['css-url-add'], array(), $css_version); | |
} | |
} | |
// 管理画面のサブメニュー追加 | |
public function add_menu() { | |
$menu_manager = __('Pz LkC Cache', $this->text_domain); | |
$menu_settings = __('Pz LinkCard', $this->text_domain); | |
if ($this->options['flg-alive'] && $this->options['flg-alive-count']) { | |
global $wpdb; | |
$result = $wpdb->get_row("SELECT COUNT(*) AS count FROM $this->db_name WHERE alive_result = '404'"); | |
if (isset($result) && isset($result->count)) { | |
$menu_manager .= ' <span class="update-plugins"><span class="update-count lkc-menu-count">'.$result->count.'</span></span>'; | |
} | |
} | |
add_management_page (__('LinkCard cache manager', $this->text_domain), $menu_manager, 'manage_options', 'pz-linkcard-cache', array($this, 'page_cacheman') ); | |
add_options_page (__('LinkCard Settings', $this->text_domain), $menu_settings, 'manage_options', 'pz-linkcard-settings', array($this, 'page_settings') ); | |
} | |
// WP-CRONスケジュール(SNSカウント取得) | |
public function schedule_hook_check() { | |
if (!isset($this->options['sns-position']) || $this->options['sns-position'] == '') { | |
return null; | |
} | |
global $wpdb; | |
$result = (array) $wpdb->get_results($wpdb->prepare("SELECT url,sns_nexttime FROM $this->db_name WHERE sns_nexttime<%d ORDER BY sns_nexttime ASC", $this->now)); | |
$i = 0; | |
if (isset($result) && is_array($result) && count($result) > 0) { | |
foreach($result as $data) { | |
$i++; | |
if ($i > 10) { | |
wp_schedule_single_event(time() + 30, 'pz_linkcard_check'); | |
break; | |
} | |
if (isset($data) && isset($data->url)) { | |
$data = $this->pz_RenewSNSCount(array('url' => $data->url) ); | |
} | |
} | |
} | |
} | |
// WP-CRONスケジュール(存在チェック) | |
public function schedule_hook_alive() { | |
if (!isset($this->options['flg-alive']) || $this->options['flg-alive'] == '') { | |
return null; | |
} | |
global $wpdb; | |
$result = (array) $wpdb->get_results($wpdb->prepare("SELECT url,alive_time FROM $this->db_name WHERE alive_nexttime<%d ORDER BY alive_time ASC, id ASC", $this->now - WEEK_IN_SECONDS )); | |
$i = 0; | |
if (isset($result) && is_array($result) && count($result) > 0) { | |
foreach($result as $data) { | |
$i++; | |
if ($i > 5) { | |
wp_schedule_single_event(time() + 3600, 'pz_linkcard_alive'); | |
break; | |
} | |
if (isset($data) && isset($data->url)) { | |
$before = $this->pz_GetCache( array( 'url' => $data->url ) ); | |
$after = $this->pz_GetCURL( $before ); | |
if ($before['title'] == $after['title'] ) { | |
$before['mod_title'] = 0; | |
} else { | |
$before['mod_title'] = 1; | |
} | |
if ($before['excerpt'] == $after['excerpt'] ) { | |
$before['mod_excerpt'] = 0; | |
} else { | |
$before['mod_excerpt'] = 1; | |
} | |
$before['alive_result'] = $after['result_code']; | |
$before['alive_time'] = $this->now; | |
$before['alive_nexttime'] = $this->now + WEEK_IN_SECONDS * 4 + rand(0, DAY_IN_SECONDS); | |
$before['thumbnail'] = $after['thumbnail']; | |
$before['favicon'] = $after['favicon']; | |
$before = $this->pz_SetCache( $before ); | |
} | |
} | |
} | |
} | |
// スタイルシート生成 | |
private function pz_SetStyle() { | |
require('lib/pz-linkcard-style.php'); | |
} | |
// Pz カード管理 キャッシュ・マネージャ | |
public function page_cacheman() { | |
require('lib/pz-linkcard-cacheman.php'); | |
} | |
// Pz カード 設定画面 | |
public function page_settings() { | |
require('lib/pz-linkcard-settings.php'); | |
} | |
// プラグイン一覧のクイックメニュー | |
public function action_links($links ) { | |
$links = array('<a href="options-general.php?page=pz-linkcard-settings">'.__('Settings', $this->text_domain).'</a>' , '<a href="tools.php?page=pz-linkcard-cache">'.__('Manage', $this->text_domain).'</a>' ) + $links; | |
return $links; | |
} | |
// プラグイン有効化 | |
public function activate() { | |
require('lib/pz-linkcard-init.php'); | |
} | |
// プラグイン停止 | |
public function deactivate() { | |
wp_clear_scheduled_hook('pz_linkcard_check'); | |
wp_clear_scheduled_hook('pz_linkcard_alive'); | |
} | |
} | |
$Class_Pz_LinkCard = new Pz_LinkCard; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment