functions.php 110 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647
  1. <?php
  2. /**
  3. * iro functions and definitions.
  4. *
  5. * @link https://developer.wordpress.org/themes/basics/theme-functions/
  6. *
  7. * @package iro
  8. */
  9. include_once('inc/classes/IpLocation.php');
  10. define('IRO_VERSION', wp_get_theme()->get('Version'));
  11. define('INT_VERSION', '19.2.0');
  12. define('BUILD_VERSION', '2');
  13. function check_php_version($preset_version)
  14. {
  15. $current_version = phpversion();
  16. return version_compare($current_version, $preset_version, '>=') ? true : false;
  17. }
  18. //Option-Framework
  19. require get_template_directory() . '/opt/option-framework.php';
  20. if (!function_exists('iro_opt')) {
  21. $GLOBALS['iro_options'] = get_option('iro_options');
  22. function iro_opt($option = '', $default = null)
  23. {
  24. return $GLOBALS['iro_options'][$option] ?? $default;
  25. }
  26. }
  27. if (!function_exists('iro_opt_update')) {
  28. function iro_opt_update($option = '', $value = null)
  29. {
  30. $options = get_option('iro_options'); // 当数据库没有指定项时,WordPress会返回false
  31. if ($options) {
  32. $options[$option] = $value;
  33. } else {
  34. $options = array($option => $value);
  35. }
  36. update_option('iro_options', $options);
  37. }
  38. }
  39. $shared_lib_basepath = iro_opt('shared_library_basepath') ? get_template_directory_uri() : (iro_opt('lib_cdn_path', 'https://fastly.jsdelivr.net/gh/mirai-mamori/Sakurairo@') . IRO_VERSION);
  40. $core_lib_basepath = iro_opt('core_library_basepath') ? get_template_directory_uri() : (iro_opt('lib_cdn_path', 'https://fastly.jsdelivr.net/gh/mirai-mamori/Sakurairo@') . IRO_VERSION);
  41. /**
  42. * composer autoload
  43. */
  44. if ((check_php_version('7.4.0')) && iro_opt('composer_load')) {
  45. require_once 'vendor/autoload.php';
  46. }
  47. //Update-Checker
  48. require 'update-checker/update-checker.php';
  49. use YahnisElsts\PluginUpdateChecker\v5\PucFactory;
  50. function UpdateCheck($url, $flag = 'Sakurairo')
  51. {
  52. return PucFactory::buildUpdateChecker(
  53. $url,
  54. __FILE__,
  55. $flag
  56. );
  57. }
  58. switch (iro_opt('iro_update_source')) {
  59. case 'github':
  60. $iroThemeUpdateChecker = UpdateCheck('https://github.com/mirai-mamori/Sakurairo', 'Sakurairo');
  61. break;
  62. case 'upyun':
  63. $iroThemeUpdateChecker = UpdateCheck('https://update.maho.cc/jsdelivr.json');
  64. break;
  65. case 'official_building':
  66. $iroThemeUpdateChecker = UpdateCheck('https://update.maho.cc/' . iro_opt('iro_update_channel') . '/check.json');
  67. }
  68. //ini_set('display_errors', true);
  69. //error_reporting(E_ALL);
  70. error_reporting(E_ALL & ~E_NOTICE);
  71. if (!function_exists('akina_setup')) {
  72. function akina_setup()
  73. {
  74. /*
  75. * Make theme available for translation.
  76. * Translations can be filed in the /languages/ directory.
  77. * If you're building a theme based on Akina, use a find and replace
  78. * to change 'akina' to the name of your theme in all the template files.
  79. */
  80. load_theme_textdomain('sakurairo', get_template_directory() . '/languages');
  81. /*
  82. * Enable support for Post Thumbnails on posts and pages.
  83. *
  84. * @link https://developer.wordpress.org/themes/functionality/featured-images-post-thumbnails/
  85. */
  86. add_theme_support('post-thumbnails');
  87. set_post_thumbnail_size(150, 150, true);
  88. // This theme uses wp_nav_menu() in one location.
  89. register_nav_menus(
  90. array(
  91. 'primary' => __('Nav Menus', 'sakurairo'), //导航菜单
  92. )
  93. );
  94. /*
  95. * Switch default core markup for search form, comment form, and comments
  96. * to output valid HTML5.
  97. */
  98. add_theme_support(
  99. 'html5',
  100. array(
  101. 'search-form',
  102. 'comment-form',
  103. 'comment-list',
  104. 'gallery',
  105. 'caption',
  106. )
  107. );
  108. /*
  109. * Enable support for Post Formats.
  110. * See https://developer.wordpress.org/themes/functionality/post-formats/
  111. */
  112. add_theme_support(
  113. 'post-formats',
  114. array(
  115. 'aside',
  116. 'image',
  117. 'status',
  118. )
  119. );
  120. // Set up the WordPress core custom background feature.
  121. add_theme_support(
  122. 'custom-background',
  123. apply_filters(
  124. 'akina_custom_background_args',
  125. array(
  126. 'default-color' => 'ffffff',
  127. 'default-image' => '',
  128. )
  129. )
  130. );
  131. /**
  132. * 废弃过时的wp_title
  133. * @seealso https://make.wordpress.org/core/2015/10/20/document-title-in-4-4/
  134. */
  135. add_theme_support('title-tag');
  136. add_filter('pre_option_link_manager_enabled', '__return_true');
  137. // 优化代码
  138. //去除头部冗余代码
  139. remove_action('wp_head', 'feed_links_extra', 3);
  140. remove_action('wp_head', 'rsd_link');
  141. remove_action('wp_head', 'wlwmanifest_link');
  142. remove_action('wp_head', 'index_rel_link');
  143. remove_action('wp_head', 'start_post_rel_link', 10);
  144. remove_action('wp_head', 'wp_generator');
  145. remove_filter('the_content', 'wptexturize');
  146. remove_action('template_redirect', 'rest_output_link_header', 11);
  147. function coolwp_remove_open_sans_from_wp_core()
  148. {
  149. wp_deregister_style('open-sans');
  150. wp_register_style('open-sans', false);
  151. wp_enqueue_style('open-sans', '');
  152. }
  153. add_action('init', 'coolwp_remove_open_sans_from_wp_core');
  154. if (!function_exists('disable_emojis')) {
  155. /**
  156. * Disable the emoji's
  157. * @see https://wordpress.org/plugins/disable-emojis/
  158. */
  159. function disable_emojis()
  160. {
  161. remove_action('wp_head', 'print_emoji_detection_script', 7);
  162. remove_action('admin_print_scripts', 'print_emoji_detection_script');
  163. remove_action('wp_print_styles', 'print_emoji_styles');
  164. remove_action('admin_print_styles', 'print_emoji_styles');
  165. remove_filter('the_content_feed', 'wp_staticize_emoji');
  166. remove_filter('comment_text_rss', 'wp_staticize_emoji');
  167. remove_filter('wp_mail', 'wp_staticize_emoji_for_email');
  168. add_filter('tiny_mce_plugins', 'disable_emojis_tinymce');
  169. }
  170. add_action('init', 'disable_emojis');
  171. }
  172. if (!function_exists('disable_emojis_tinymce')) {
  173. /**
  174. * Filter function used to remove the tinymce emoji plugin.
  175. *
  176. * @param array $plugins
  177. * @return array Difference betwen the two arrays
  178. */
  179. function disable_emojis_tinymce($plugins)
  180. {
  181. if (is_array($plugins)) {
  182. return array_diff($plugins, array('wpemoji'));
  183. } else {
  184. return array();
  185. }
  186. }
  187. }
  188. // 移除菜单冗余代码
  189. add_filter('nav_menu_css_class', 'my_css_attributes_filter', 100, 1);
  190. add_filter('nav_menu_item_id', 'my_css_attributes_filter', 100, 1);
  191. add_filter('page_css_class', 'my_css_attributes_filter', 100, 1);
  192. function my_css_attributes_filter($var)
  193. {
  194. return is_array($var) ? array_intersect($var, array('current-menu-item', 'current-post-ancestor', 'current-menu-ancestor', 'current-menu-parent')) : '';
  195. }
  196. }
  197. }
  198. ;
  199. add_action('after_setup_theme', 'akina_setup');
  200. function register_shuoshuo_post_type() {
  201. $labels = array(
  202. 'name' => _x('Shuoshuo', 'post type general name', 'sakurairo'),
  203. 'singular_name' => _x('Shuoshuo', 'post type singular name', 'sakurairo'),
  204. 'menu_name' => _x('Shuoshuo', 'admin menu', 'sakurairo'),
  205. 'name_admin_bar' => _x('Shuoshuo', 'add new on admin bar', 'sakurairo'),
  206. 'add_new' => _x('Add New', 'shuoshuo', 'sakurairo'),
  207. 'add_new_item' => __('Add New Shuoshuo', 'sakurairo'),
  208. 'new_item' => __('New Shuoshuo', 'sakurairo'),
  209. 'edit_item' => __('Edit Shuoshuo', 'sakurairo'),
  210. 'view_item' => __('View Shuoshuo', 'sakurairo'),
  211. 'all_items' => __('All Shuoshuo', 'sakurairo'),
  212. 'search_items' => __('Search Shuoshuo', 'sakurairo'),
  213. 'parent_item_colon' => __('Parent Shuoshuo:', 'sakurairo'),
  214. 'not_found' => __('No shuoshuo found.', 'sakurairo'),
  215. 'not_found_in_trash' => __('No shuoshuo found in Trash.', 'sakurairo')
  216. );
  217. $args = array(
  218. 'labels' => $labels,
  219. 'public' => true,
  220. 'publicly_queryable' => true,
  221. 'show_ui' => true,
  222. 'show_in_menu' => true,
  223. 'show_in_rest' => true,
  224. 'query_var' => true,
  225. 'rewrite' => array('slug' => 'shuoshuo'),
  226. 'capability_type' => 'post',
  227. 'has_archive' => true,
  228. 'hierarchical' => false,
  229. 'menu_position' => null,
  230. 'supports' => array('title', 'editor', 'author', 'thumbnail', 'custom-fields', 'comments'),
  231. 'taxonomies' => array('category')
  232. );
  233. register_post_type('shuoshuo', $args);
  234. }
  235. add_action('init', 'register_shuoshuo_post_type');
  236. function register_emotion_meta_boxes() {
  237. register_meta('post', 'emotion', array(
  238. 'show_in_rest' => true,
  239. 'single' => true,
  240. 'type' => 'string',
  241. 'auth_callback' => function() {
  242. return current_user_can('edit_posts');
  243. }
  244. ));
  245. register_meta('post', 'emotion_color', array(
  246. 'show_in_rest' => true,
  247. 'single' => true,
  248. 'type' => 'string',
  249. 'auth_callback' => function() {
  250. return current_user_can('edit_posts');
  251. }
  252. ));
  253. }
  254. add_action('init', 'register_emotion_meta_boxes');
  255. function add_emotion_meta_box() {
  256. add_meta_box(
  257. 'emotion_meta_box_id',
  258. __('Emotion Meta Box', 'sakurairo'),
  259. 'render_emotion_meta_box',
  260. 'shuoshuo', // 仅在shuoshuo内容类型中显示
  261. 'side',
  262. 'default'
  263. );
  264. }
  265. add_action('add_meta_boxes', 'add_emotion_meta_box');
  266. function render_emotion_meta_box($post) {
  267. $emotion_value = get_post_meta($post->ID, 'emotion', true);
  268. $emotion_color_value = get_post_meta($post->ID, 'emotion_color', true);
  269. wp_nonce_field('emotion_meta_box_nonce', 'emotion_meta_box_nonce_field');
  270. echo '<label for="emotion">' . __('Emotion', 'sakurairo') . '</label>';
  271. echo '<input type="text" id="emotion" name="emotion" value="' . esc_attr($emotion_value) . '" />';
  272. echo '<br><br>';
  273. echo '<label for="emotion_color">' . __('Emotion Color', 'sakurairo') . '</label>';
  274. echo '<input type="text" id="emotion_color" name="emotion_color" value="' . esc_attr($emotion_color_value) . '" />';
  275. echo '<br><br>';
  276. echo '<p>' . __('For the Emotion, please fill in the Unicode value of the Fontawesome icon, and for the Emotion Color, please fill in the RGBA or hexadecimal color.', 'sakurairo') . '</p>';
  277. }
  278. function save_emotion_meta_box($post_id) {
  279. if (!isset($_POST['emotion_meta_box_nonce_field']) || !wp_verify_nonce($_POST['emotion_meta_box_nonce_field'], 'emotion_meta_box_nonce')) {
  280. return;
  281. }
  282. if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
  283. return;
  284. }
  285. if (!current_user_can('edit_post', $post_id)) {
  286. return;
  287. }
  288. if (isset($_POST['emotion'])) {
  289. update_post_meta($post_id, 'emotion', sanitize_text_field($_POST['emotion']));
  290. }
  291. if (isset($_POST['emotion_color'])) {
  292. update_post_meta($post_id, 'emotion_color', sanitize_text_field($_POST['emotion_color']));
  293. }
  294. }
  295. add_action('save_post', 'save_emotion_meta_box');
  296. function register_custom_meta_boxes() {
  297. register_meta('post', 'title_style', array(
  298. 'show_in_rest' => true,
  299. 'single' => true,
  300. 'type' => 'string',
  301. 'auth_callback' => function() {
  302. return current_user_can('edit_posts');
  303. }
  304. ));
  305. register_meta('post', 'license', array(
  306. 'show_in_rest' => true,
  307. 'single' => true,
  308. 'type' => 'string',
  309. 'auth_callback' => function() {
  310. return current_user_can('edit_posts');
  311. }
  312. ));
  313. }
  314. add_action('init', 'register_custom_meta_boxes');
  315. function add_custom_meta_box() {
  316. add_meta_box(
  317. 'custom_meta_box_id',
  318. __('Custom Meta Box', 'sakurairo'),
  319. 'render_custom_meta_box',
  320. 'post', // 仅在post内容类型中显示
  321. 'side',
  322. 'default'
  323. );
  324. }
  325. add_action('add_meta_boxes', 'add_custom_meta_box');
  326. function render_custom_meta_box($post) {
  327. $title_style_value = get_post_meta($post->ID, 'title_style', true);
  328. $license_value = get_post_meta($post->ID, 'license', true);
  329. wp_nonce_field('custom_meta_box_nonce', 'custom_meta_box_nonce_field');
  330. echo '<label for="title_style">' . __('Title Style', 'sakurairo') . '</label>';
  331. echo '<input type="text" id="title_style" name="title_style" value="' . esc_attr($title_style_value) . '" />';
  332. echo '<br><br>';
  333. echo '<label for="license">' . __('License', 'sakurairo') . '</label>';
  334. echo '<input type="text" id="license" name="license" value="' . esc_attr($license_value) . '" />';
  335. echo '<br><br>';
  336. echo '<p>' . __('For the Title Style, Please fill in the css style, part of the style need to add !important effective, and for the License, please go to Theme Options to learn how to set it up.', 'sakurairo') . '</p>';
  337. }
  338. function save_custom_meta_box($post_id) {
  339. if (!isset($_POST['custom_meta_box_nonce_field']) || !wp_verify_nonce($_POST['custom_meta_box_nonce_field'], 'custom_meta_box_nonce')) {
  340. return;
  341. }
  342. if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
  343. return;
  344. }
  345. if (!current_user_can('edit_post', $post_id)) {
  346. return;
  347. }
  348. if (isset($_POST['title_style'])) {
  349. update_post_meta($post_id, 'title_style', sanitize_text_field($_POST['title_style']));
  350. }
  351. if (isset($_POST['license'])) {
  352. update_post_meta($post_id, 'license', sanitize_text_field($_POST['license']));
  353. }
  354. }
  355. add_action('save_post', 'save_custom_meta_box');
  356. function include_shuoshuo_in_main_query($query) {
  357. if ($query->is_main_query() && !is_admin() && (is_home() || is_archive())) {
  358. $query->set('post_type', array('post', 'shuoshuo'));
  359. }
  360. }
  361. add_action('pre_get_posts', 'include_shuoshuo_in_main_query');
  362. function admin_lettering()
  363. {
  364. echo '<style>body{font-family: Microsoft YaHei;}</style>';
  365. }
  366. add_action('admin_head', 'admin_lettering');
  367. /**
  368. * Set the content width in pixels, based on the theme's design and stylesheet.
  369. *
  370. * Priority 0 to make it available to lower priority callbacks.
  371. *
  372. * @global int $content_width
  373. */
  374. function akina_content_width()
  375. {
  376. $GLOBALS['content_width'] = apply_filters('akina_content_width', 640);
  377. }
  378. add_action('after_setup_theme', 'akina_content_width', 0);
  379. /**
  380. * Enqueue scripts and styles.
  381. */
  382. function sakura_scripts()
  383. {
  384. global $core_lib_basepath;
  385. global $shared_lib_basepath;
  386. wp_enqueue_style('saukra-css', $core_lib_basepath . '/style.css', array(), IRO_VERSION);
  387. if(!is_404()){
  388. wp_enqueue_script('app', $core_lib_basepath . '/js/app.js', array('polyfills'), IRO_VERSION, true);
  389. if (!is_home()) {
  390. //非主页的资源
  391. wp_enqueue_style(
  392. 'entry-content',
  393. $core_lib_basepath . '/css/theme/' . (iro_opt('entry_content_style') == 'sakurairo' ? 'sakura' : 'github') . '.css',
  394. array(),
  395. IRO_VERSION
  396. );
  397. wp_enqueue_script('app-page', $core_lib_basepath . '/js/page.js', array('app', 'polyfills'), IRO_VERSION, true);
  398. }
  399. }
  400. wp_enqueue_script('polyfills', $core_lib_basepath . '/js/polyfill.js', array(), IRO_VERSION, true);
  401. if (is_singular() && comments_open() && get_option('thread_comments')) {
  402. wp_enqueue_script('comment-reply');
  403. }
  404. //前端脚本本地化
  405. if (get_locale() != 'zh_CN') {
  406. wp_localize_script(
  407. 'app',
  408. '_sakurairoi18n',
  409. array(
  410. '复制成功!' => __("Copied!", 'sakurairo'),
  411. '拷贝代码' => __("Copy Code", 'sakurairo'),
  412. '你的封面API好像不支持跨域调用,这种情况下缓存是不会生效的哦' => __("Your cover API seems to not support Cross Origin Access. In this case, Cover Cache won't take effect.", 'sakurairo'),
  413. '提交中....' => __('Commiting....', 'sakurairo'),
  414. '提交成功' => __('Succeed', 'sakurairo'),
  415. '每次上传上限为10张' => __('10 files max per request', 'sakurairo'),
  416. "图片上传大小限制为5 MB\n\n「{0}」\n\n这张图太大啦~请重新上传噢!" => __("5 MB max per file.\n\n「{0}」\n\nThis image is too large~Please reupload!", 'sakurairo'),
  417. '上传中...' => __('Uploading...', 'sakurairo'),
  418. '图片上传成功~' => __('Uploaded successfully~', 'sakurairo'),
  419. "上传失败!\n文件名=> {0}\ncode=> {1}\n{2}" => __("Upload failed!\nFile Name=> {0}\ncode=> {1}\n{2}", 'sakurairo'),
  420. '上传失败,请重试.' => __('Upload failed, please retry.', 'sakurairo'),
  421. '页面加载出错了 HTTP {0}' => __("Page Load failed. HTTP {0}", 'sakurairo'),
  422. '很高兴你翻到这里,但是真的没有了...' => __("Glad you come, but we've got nothing left.", 'sakurairo'),
  423. "文章" => __("Post", 'sakurairo'),
  424. "标签" => __("Tag", 'sakurairo'),
  425. "分类" => __("Category", 'sakurairo'),
  426. "页面" => __("Page", 'sakurairo'),
  427. "评论" => __("Comment", 'sakurairo'),
  428. "已暂停..." => __("Paused...", 'sakurairo'),
  429. "正在载入视频 ..." => __("Loading Video...", 'sakurairo'),
  430. "将从网络加载字体,流量请注意" => __("Downloading fonts, be aware of your data usage.", 'sakurairo'),
  431. "您真的要设为私密吗?" => __("Are you sure you want set it private?", 'sakurairo'),
  432. "您之前已设过私密评论" => __("You had set private comment before", 'sakurairo')
  433. )
  434. );
  435. }
  436. if (iro_opt('smoothscroll_option')) {
  437. wp_enqueue_script('SmoothScroll', $shared_lib_basepath . '/js/smoothscroll.js', array(), IRO_VERSION . iro_opt('cookie_version', ''), true);
  438. }
  439. }
  440. add_action('wp_enqueue_scripts', 'sakura_scripts');
  441. /**
  442. * load .php.
  443. */
  444. require get_template_directory() . '/inc/decorate.php';
  445. require get_template_directory() . '/inc/swicher.php';
  446. require get_template_directory() . '/inc/api.php';
  447. /**
  448. * Custom template tags for this theme.
  449. */
  450. require get_template_directory() . '/inc/template-tags.php';
  451. /**
  452. * Customizer additions.
  453. */
  454. require get_template_directory() . '/inc/customizer.php';
  455. /**
  456. * function update
  457. */
  458. require get_template_directory() . '/inc/theme_plus.php';
  459. require get_template_directory() . '/inc/categories-images.php';
  460. if (!function_exists('akina_comment_format')) {
  461. function akina_comment_format($comment, $args, $depth)
  462. {
  463. $GLOBALS['comment'] = $comment;
  464. ?>
  465. <li <?php comment_class(); ?> id="comment-<?php echo esc_attr(comment_ID()); ?>">
  466. <div class="contents">
  467. <div class="comment-arrow">
  468. <div class="main shadow">
  469. <div class="profile">
  470. <a href="<?php comment_author_url(); ?>" target="_blank" rel="nofollow"><?php echo str_replace('src=', 'src="' . iro_opt('load_in_svg') . '" onerror="imgError(this,1)" data-src=', get_avatar($comment->comment_author_email, 80, '', get_comment_author(), array('class' => array('lazyload')))); ?></a>
  471. </div>
  472. <div class="commentinfo">
  473. <section class="commeta">
  474. <div class="left">
  475. <h4 class="author">
  476. <a href="<?php comment_author_url(); ?>" target="_blank" rel="nofollow"><?php echo get_avatar($comment->comment_author_email, 24, '', get_comment_author()); ?>
  477. <span class="bb-comment isauthor" title="<?php _e('Author', 'sakurairo'); ?>"><?php _e('Blogger', 'sakurairo'); /*博主*/?></span>
  478. <?php comment_author(); ?><?php echo get_author_class($comment->comment_author_email, $comment->user_id); ?>
  479. </a>
  480. </h4>
  481. </div>
  482. <?php comment_reply_link(array_merge($args, array('depth' => $depth, 'max_depth' => $args['max_depth']))); ?>
  483. <div class="right">
  484. <div class="info"><time datetime="<?php comment_date('Y-m-d'); ?>"><?php echo poi_time_since(strtotime($comment->comment_date), true); //comment_date(get_option('date_format'));
  485. ?></time><?= siren_get_useragent($comment->comment_agent); ?><?php echo mobile_get_useragent_icon($comment->comment_agent); ?>&nbsp;<?php if (iro_opt('comment_location')) {
  486. _e('Location', 'sakurairo'); /*来自*/?>: <?php echo \Sakura\API\IpLocationParse::getIpLocationByCommentId($comment->comment_ID);
  487. } ?>
  488. <?php if (current_user_can('manage_options') and (wp_is_mobile() == false)) {
  489. $comment_ID = $comment->comment_ID;
  490. $i_private = get_comment_meta($comment_ID, '_private', true);
  491. $flag = null;
  492. $flag .= ' <i class="fa-regular fa-snowflake"></i> <a href="javascript:;" data-actionp="set_private" data-idp="' . get_comment_id() . '" id="sp" class="sm">' . __("Private", "sakurairo") . ': <span class="has_set_private">';
  493. if (!empty($i_private)) {
  494. $flag .= __("Yes", "sakurairo") . ' <i class="fa-solid fa-lock"></i>';
  495. } else {
  496. $flag .= __("No", "sakurairo") . ' <i class="fa-solid fa-lock-open"></i>';
  497. }
  498. $flag .= '</span></a>';
  499. $flag .= edit_comment_link('<i class="fa-solid fa-pen-to-square"></i> ' . __("Edit", "mashiro"), ' <span style="color:rgba(0,0,0,.35)">', '</span>');
  500. echo $flag;
  501. } ?></div>
  502. </div>
  503. </section>
  504. </div>
  505. <div class="body">
  506. <?php comment_text(); ?>
  507. </div>
  508. </div>
  509. <div class="arrow-left"></div>
  510. </div>
  511. </div>
  512. <hr>
  513. <?php
  514. }
  515. }
  516. /**
  517. * 获取访客VIP样式
  518. */
  519. function get_author_class($comment_author_email, $user_id)
  520. {
  521. global $wpdb;
  522. $author_count = count(
  523. $wpdb->get_results(
  524. "SELECT comment_ID as author_count FROM $wpdb->comments WHERE comment_author_email = '$comment_author_email' "
  525. )
  526. );
  527. # 等级梯度
  528. $lv_array = [0, 5, 10, 20, 40, 80, 160];
  529. $Lv = 0;
  530. foreach ($lv_array as $key => $value) {
  531. if ($value >= $author_count)
  532. break;
  533. $Lv = $key;
  534. }
  535. // $Lv = $author_count < 5 ? 0 : ($author_count < 10 ? 1 : ($author_count < 20 ? 2 : ($author_count < 40 ? 3 : ($author_count < 80 ? 4 : ($author_count < 160 ? 5 : 6)))));
  536. echo "<span class=\"showGrade{$Lv}\" title=\"Lv{$Lv}\"><img alt=\"level_img\" src=\"" . iro_opt('vision_resource_basepath', 'https://s.nmxc.ltd/sakurairo_vision/@2.7/') . "comment_level/level_{$Lv}.svg\" style=\"height: 1.5em; max-height: 1.5em; display: inline-block;\"></span>";
  537. }
  538. /**
  539. * post views
  540. */
  541. function restyle_text($number)
  542. {
  543. switch (iro_opt('statistics_format')) {
  544. case "type_2": //23,333 次访问
  545. return number_format($number);
  546. case "type_3": //23 333 次访问
  547. return number_format($number, 0, '.', ' ');
  548. case "type_4": //23k 次访问
  549. if ($number >= 1000) {
  550. return round($number / 1000, 2) . 'k';
  551. }
  552. return $number;
  553. default:
  554. return $number;
  555. }
  556. }
  557. function set_post_views()
  558. {
  559. if (!is_singular())
  560. return;
  561. global $post;
  562. $post_id = intval($post->ID);
  563. if (!$post_id)
  564. return;
  565. $views = (int) get_post_meta($post_id, 'views', true);
  566. if (!update_post_meta($post_id, 'views', ($views + 1))) {
  567. add_post_meta($post_id, 'views', 1, true);
  568. }
  569. }
  570. add_action('get_header', 'set_post_views');
  571. function get_post_views($post_id)
  572. {
  573. // 检查传入的参数是否有效
  574. if (empty($post_id) || !is_numeric($post_id)) {
  575. return 'Error: Invalid post ID.';
  576. }
  577. // 检查 WP-Statistics 插件是否安装
  578. if ((function_exists('wp_statistics_pages')) && (iro_opt('statistics_api') == 'wp_statistics')) {
  579. // 使用 WP-Statistics 插件获取浏览量
  580. $views = wp_statistics_pages('total', 'uri', $post_id);
  581. return empty($views) ? 0 : $views;
  582. } else {
  583. // 使用文章自定义字段获取浏览量
  584. $views = get_post_meta($post_id, 'views', true);
  585. // 格式化浏览量
  586. $views = restyle_text($views);
  587. return empty($views) ? 0 : $views;
  588. }
  589. }
  590. function is_webp(): bool
  591. {
  592. return (isset($_COOKIE['su_webp']) || (isset($_SERVER['HTTP_ACCEPT']) && strpos($_SERVER['HTTP_ACCEPT'], 'image/webp')));
  593. }
  594. /**
  595. * 获取友情链接列表
  596. * @Param: string $sorting_mode 友情链接列表排序模式,name、updated、rating、rand四种模式
  597. * @Param: string $link_order 友情链接列表排序方法,ASC、DESC(升序或降序)
  598. * @Param: mixed $id 友情链接ID
  599. * @Param: string $output HTML格式化输出
  600. */
  601. function get_the_link_items($id = null)
  602. {
  603. $sorting_mode = iro_opt('friend_link_sorting_mode');
  604. $link_order = iro_opt('friend_link_order');
  605. $bookmarks = get_bookmarks(
  606. array(
  607. 'orderby' => $sorting_mode,
  608. 'order' => $link_order,
  609. 'category' => $id
  610. )
  611. );
  612. $output = '';
  613. if (!empty($bookmarks)) {
  614. $output .= '<ul class="link-items fontSmooth">';
  615. foreach ($bookmarks as $bookmark) {
  616. if (empty($bookmark->link_description)) {
  617. $bookmark->link_description = __('This guy is so lazy ╮(╯▽╰)╭', 'sakurairo');
  618. }
  619. if (empty($bookmark->link_image)) {
  620. $bookmark->link_image = 'https://s.nmxc.ltd/sakurairo_vision/@2.7/basic/friendlink.jpg';
  621. }
  622. $output .= '<li class="link-item"><a class="link-item-inner effect-apollo" href="' . $bookmark->link_url . '" title="' . $bookmark->link_description . '" target="_blank" rel="friend"><img alt="friend_avator" class="lazyload" onerror="imgError(this,1)" data-src="' . $bookmark->link_image . '" src="' . iro_opt('load_in_svg') . '"></br><span class="sitename" style="' . $bookmark->link_notes . '">' . $bookmark->link_name . '</span><div class="linkdes">' . $bookmark->link_description . '</div></a></li>';
  623. }
  624. $output .= '</ul>';
  625. }
  626. return $output;
  627. }
  628. function get_link_items()
  629. {
  630. $linkcats = get_terms('link_category');
  631. $result = null;
  632. if (empty($linkcats))
  633. return get_the_link_items(); // 友链无分类,直接返回全部列表
  634. $link_category_need_display = get_post_meta(get_queried_object_id(), 'link_category_need_display', false);
  635. foreach ($linkcats as $linkcat) {
  636. if (!empty($link_category_need_display) && !in_array($linkcat->name, $link_category_need_display, true)) {
  637. continue;
  638. }
  639. $result .= '<h3 class="link-title"><span class="link-fix">' . $linkcat->name . '</span></h3>';
  640. if ($linkcat->description) {
  641. $result .= '<div class="link-description">' . $linkcat->description . '</div>';
  642. }
  643. $result .= get_the_link_items($linkcat->term_id);
  644. }
  645. return $result;
  646. }
  647. /*
  648. * Gravatar头像使用中国服务器
  649. */
  650. function gravatar_cn(string $url): string
  651. {
  652. $gravatar_url = array('0.gravatar.com/avatar', '1.gravatar.com/avatar', '2.gravatar.com/avatar', 'secure.gravatar.com/avatar');
  653. if (iro_opt('gravatar_proxy') == 'custom_proxy_address_of_gravatar') {
  654. return str_replace($gravatar_url, iro_opt('custom_proxy_address_of_gravatar'), $url);
  655. } else {
  656. return str_replace($gravatar_url, iro_opt('gravatar_proxy'), $url);
  657. }
  658. }
  659. if (iro_opt('gravatar_proxy')) {
  660. add_filter('get_avatar_url', 'gravatar_cn', 4);
  661. }
  662. /*
  663. * 检查主题版本号,并在更新主题后执行设置选项值的更新
  664. */
  665. function visual_resource_updates($specified_version, $option_name, $new_value)
  666. {
  667. $theme = wp_get_theme();
  668. $current_version = $theme->get('Version');
  669. // Check if the function has already been triggered
  670. $function_triggered = get_transient('visual_resource_updates_triggered19');
  671. if ($function_triggered) {
  672. return; // Function has already been triggered, do nothing
  673. }
  674. if (version_compare($current_version, $specified_version, '>')) {
  675. $option_value = iro_opt($option_name);
  676. if (empty($option_value)) {
  677. $option_value = "https://s.nmxc.ltd/sakurairo_vision/@2.7/";
  678. } else if (strpos($option_value, '@') === false || substr($option_value, strpos($option_value, '@') + 1) !== $new_value) {
  679. $option_value = preg_replace('/@.*/', '@' . $new_value, $option_value);
  680. }
  681. iro_opt_update($option_name, $option_value);
  682. // Set transient to indicate that the function has been triggered
  683. set_transient('visual_resource_updates_triggered19', true);
  684. }
  685. }
  686. visual_resource_updates('2.5.6', 'vision_resource_basepath', '2.7/');
  687. function gfonts_updates($specified_version, $option_name)
  688. {
  689. $theme = wp_get_theme();
  690. $current_version = $theme->get('Version');
  691. // Check if the function has already been triggered
  692. $function_triggered = get_transient('gfonts_updates_triggered19');
  693. if ($function_triggered) {
  694. return; // Function has already been triggered, do nothing
  695. }
  696. if (version_compare($current_version, $specified_version, '>')) {
  697. $option_value = iro_opt($option_name);
  698. if (empty($option_value) || $option_value !== 'fonts.googleapis.com') {
  699. $option_value = 'fonts.googleapis.com';
  700. iro_opt_update($option_name, $option_value);
  701. }
  702. // Set transient to indicate that the function has been triggered
  703. set_transient('gfonts_updates_triggered19', true);
  704. }
  705. }
  706. gfonts_updates('2.5.6', 'gfonts_api');
  707. function gravater_updates($specified_version, $option_name)
  708. {
  709. $theme = wp_get_theme();
  710. $current_version = $theme->get('Version');
  711. // Check if the function has already been triggered
  712. $function_triggered = get_transient('gravater_updates_triggered19');
  713. if ($function_triggered) {
  714. return; // Function has already been triggered, do nothing
  715. }
  716. if (version_compare($current_version, $specified_version, '>')) {
  717. $option_value = iro_opt($option_name);
  718. if (empty($option_value) || $option_value !== 'weavatar.com/avatar') {
  719. $option_value = 'weavatar.com/avatar';
  720. iro_opt_update($option_name, $option_value);
  721. }
  722. // Set transient to indicate that the function has been triggered
  723. set_transient('gravater_updates_triggered19', true);
  724. }
  725. }
  726. gravater_updates('2.5.6', 'gravatar_proxy');
  727. /*
  728. * 阻止站内文章互相Pingback
  729. */
  730. function theme_noself_ping(&$links)
  731. {
  732. $home = get_option('home');
  733. foreach ($links as $l => $link) {
  734. if (0 === strpos($link, $home)) {
  735. unset($links[$l]);
  736. }
  737. }
  738. }
  739. add_action('pre_ping', 'theme_noself_ping');
  740. /*
  741. * 订制body类
  742. */
  743. function akina_body_classes($classes)
  744. {
  745. // Adds a class of group-blog to blogs with more than 1 published author.
  746. if (is_multi_author()) {
  747. $classes[] = 'group-blog';
  748. }
  749. // Adds a class of hfeed to non-singular pages.
  750. if (!is_singular()) {
  751. $classes[] = 'hfeed';
  752. }
  753. // 定制中文字体class
  754. $classes[] = 'chinese-font';
  755. /*if(!wp_is_mobile()) {
  756. $classes[] = 'serif';
  757. }*/
  758. if (isset($_COOKIE['dark' . iro_opt('cookie_version', '')])) {
  759. $classes[] = $_COOKIE['dark' . iro_opt('cookie_version', '')] == '1' ? 'dark' : ' ';
  760. } else {
  761. $classes[] = ' ';
  762. }
  763. return $classes;
  764. }
  765. add_filter('body_class', 'akina_body_classes');
  766. /*
  767. * 图片CDN
  768. */
  769. add_filter('upload_dir', 'wpjam_custom_upload_dir');
  770. function wpjam_custom_upload_dir($uploads)
  771. {
  772. /* $upload_path = '';
  773. */$upload_url_path = iro_opt('image_cdn');
  774. /* if (empty($upload_path) || 'wp-content/uploads' == $upload_path) {
  775. $uploads['basedir'] = WP_CONTENT_DIR . '/uploads';
  776. } elseif (0 !== strpos($upload_path, ABSPATH)) {
  777. $uploads['basedir'] = path_join(ABSPATH, $upload_path);
  778. } else {
  779. $uploads['basedir'] = $upload_path;
  780. } */
  781. $uploads['path'] = $uploads['basedir'] . $uploads['subdir'];
  782. if ($upload_url_path) {
  783. $uploads['baseurl'] = $upload_url_path;
  784. $uploads['url'] = $uploads['baseurl'] . $uploads['subdir'];
  785. }
  786. return $uploads;
  787. }
  788. /*
  789. * 删除自带小工具
  790. */
  791. function unregister_default_widgets()
  792. {
  793. unregister_widget('WP_Widget_Pages');
  794. unregister_widget('WP_Widget_Calendar');
  795. unregister_widget('WP_Widget_Archives');
  796. unregister_widget('WP_Widget_Links');
  797. unregister_widget('WP_Widget_Meta');
  798. unregister_widget('WP_Widget_Search');
  799. //unregister_widget('WP_Widget_Text');
  800. unregister_widget('WP_Widget_Categories');
  801. unregister_widget('WP_Widget_Recent_Posts');
  802. //unregister_widget('WP_Widget_Recent_Comments');
  803. //unregister_widget('WP_Widget_RSS');
  804. //unregister_widget('WP_Widget_Tag_Cloud');
  805. unregister_widget('WP_Nav_Menu_Widget');
  806. }
  807. add_action("widgets_init", "unregister_default_widgets", 11);
  808. /**
  809. * Jetpack setup function.
  810. *
  811. * See: https://jetpack.com/support/infinite-scroll/
  812. * See: https://jetpack.com/support/responsive-videos/
  813. */
  814. function akina_jetpack_setup()
  815. {
  816. // Add theme support for Infinite Scroll.
  817. add_theme_support(
  818. 'infinite-scroll',
  819. array(
  820. 'container' => 'main',
  821. 'render' => 'akina_infinite_scroll_render',
  822. 'footer' => 'page',
  823. )
  824. );
  825. // Add theme support for Responsive Videos.
  826. add_theme_support('jetpack-responsive-videos');
  827. }
  828. add_action('after_setup_theme', 'akina_jetpack_setup');
  829. /**
  830. * Custom render function for Infinite Scroll.
  831. */
  832. function akina_infinite_scroll_render()
  833. {
  834. while (have_posts()) {
  835. the_post();
  836. get_template_part('tpl/content', is_search() ? 'search' : get_post_format());
  837. }
  838. }
  839. /*
  840. * 编辑器增强
  841. */
  842. function enable_more_buttons($buttons)
  843. {
  844. $buttons[] = 'hr';
  845. $buttons[] = 'del';
  846. $buttons[] = 'sub';
  847. $buttons[] = 'sup';
  848. $buttons[] = 'fontselect';
  849. $buttons[] = 'fontsizeselect';
  850. $buttons[] = 'cleanup';
  851. $buttons[] = 'styleselect';
  852. $buttons[] = 'wp_page';
  853. $buttons[] = 'anchor';
  854. $buttons[] = 'backcolor';
  855. return $buttons;
  856. }
  857. add_filter("mce_buttons_3", "enable_more_buttons");
  858. // 下载按钮
  859. function download($atts, $content = null)
  860. {
  861. return '<a class="download" href="' . $content . '" rel="external"
  862. target="_blank" title="' . __("Download Link", "sakurairo") . '">
  863. <span><i class="fa-solid fa-download"></i>Download</span></a>';
  864. }
  865. add_shortcode("download", "download");
  866. add_action('after_wp_tiny_mce', 'bolo_after_wp_tiny_mce');
  867. function bolo_after_wp_tiny_mce($mce_settings)
  868. {
  869. ?>
  870. <script type="text/javascript">
  871. QTags.addButton('download', '下载按钮', "[download]下载地址[/download]");
  872. function bolo_QTnextpage_arg1() {}
  873. </script>
  874. <?php }
  875. /*
  876. * 后台登录页
  877. * @M.J
  878. */
  879. //Login Page style
  880. $custom_login_switch = iro_opt('custom_login_switch');
  881. if ($custom_login_switch) {
  882. function custom_login()
  883. {
  884. require get_template_directory() . '/inc/login_addcss.php';
  885. //echo '<link rel="stylesheet" type="text/css" href="' . get_bloginfo('template_directory') . '/inc/login.css" />'."\n";
  886. echo '<link rel="stylesheet" type="text/css" href="' . get_template_directory_uri() . '/inc/login.css?' . IRO_VERSION . '" />' . "\n";
  887. //echo '<script type="text/javascript" src="'.get_bloginfo('template_directory').'/js/jquery.min.js"></script>'."\n";
  888. }
  889. add_action('login_head', 'custom_login');
  890. //Login Page Title
  891. function custom_headertitle($title)
  892. {
  893. return get_bloginfo('name');
  894. }
  895. add_filter('login_headertext', 'custom_headertitle');
  896. //Login Page Link
  897. function custom_loginlogo_url($url)
  898. {
  899. return esc_url(home_url('/'));
  900. }
  901. add_filter('login_headerurl', 'custom_loginlogo_url');
  902. //Login Page Footer
  903. function custom_html()
  904. {
  905. $loginbg = iro_opt('login_background') ?: iro_opt('vision_resource_basepath', 'https://s.nmxc.ltd/sakurairo_vision/@2.7/') . 'series/login_background.webp';
  906. ?>
  907. <script type="text/javascript">
  908. document.body.insertAdjacentHTML("afterbegin", "<div class=\"loading\"><img src=\"<?= iro_opt('vision_resource_basepath', 'https://s.nmxc.ltd/sakurairo_vision/@2.7/')
  909. ?>basic/login_loading.gif\" width=\"58\" height=\"10\"></div>");
  910. document.head.insertAdjacentHTML("afterbegin", "<style>.show{opacity:1;}.hide{opacity:0;transition: opacity 400ms;}</style>");
  911. const loading = document.querySelector(".loading"),
  912. src = "<?= $loginbg ?>",
  913. afterLoaded = () => {
  914. document.body.style.backgroundImage = `url(${src})`
  915. loading.classList.add("hide");
  916. loading.classList.remove("show");
  917. setTimeout(function() {
  918. loading.remove()
  919. }, 400);
  920. },
  921. img = document.createElement('img')
  922. img.src = src
  923. img.addEventListener('load',afterLoaded,{once:true})
  924. <?php //3秒钟内加载不到图片也移除加载中提示
  925. ?>
  926. setTimeout(afterLoaded, 3000)
  927. document.addEventListener("DOMContentLoaded", ()=>{
  928. document.querySelector("h1 a").style.backgroundImage = "url('<?= iro_opt('login_logo_img') ?>')";
  929. forgetmenot = document.querySelector(".forgetmenot");
  930. if (forgetmenot){
  931. forgetmenot.outerHTML = '<p class="forgetmenot"><?= __("Remember me", "sakurairo") ?><input name="rememberme" id="rememberme" value="forever" type="checkbox"><label for="rememberme" style="float: right;margin-top: 5px;transform: scale(2);margin-right: -10px;"></label></p>';
  932. }
  933. const captchaimg = document.getElementById("captchaimg");
  934. captchaimg && captchaimg.addEventListener("click",(e)=>{
  935. fetch("<?= rest_url('sakura/v1/captcha/create') ?>")
  936. .then(resp=>resp.json())
  937. .then(json=>{
  938. e.target.src = json["data"];
  939. document.querySelector("input[name=\'timestamp\']").value = json["time"];
  940. document.querySelector("input[name=\'id\']").value = json["id"];
  941. });
  942. })
  943. }, false);
  944. </script>
  945. <?php
  946. }
  947. add_action('login_footer', 'custom_html');
  948. }
  949. //Login message
  950. //* Add custom message to WordPress login page
  951. function smallenvelop_login_message($message)
  952. {
  953. return empty($message) ? '<p class="message"><strong>You may try 3 times for every 5 minutes!</strong></p>' : $message;
  954. }
  955. //add_filter( 'login_message', 'smallenvelop_login_message' );
  956. //Fix password reset bug </>
  957. function resetpassword_message_fix($message)
  958. {
  959. return str_replace(['>', '<'], '', $message);
  960. // $message = str_replace('<', '', $message);
  961. // $message = str_replace('>', '', $message);
  962. // return $message;
  963. }
  964. add_filter('retrieve_password_message', 'resetpassword_message_fix');
  965. //Fix register email bug </>
  966. function new_user_message_fix($message)
  967. {
  968. $show_register_ip = '注册IP | Registration IP: ' . get_the_user_ip() . ' (' . \Sakura\API\IpLocationParse::getIpLocationByIp(get_the_user_ip()) . ")\r\n\r\n如非本人操作请忽略此邮件 | Please ignore this email if this was not your operation.\r\n\r\n";
  969. $message = str_replace('To set your password, visit the following address:', $show_register_ip . '在此设置密码 | To set your password, visit the following address:', $message);
  970. $message = str_replace('<', '', $message);
  971. $message = str_replace('>', "\r\n\r\n设置密码后在此登录 | Login here after setting password: ", $message);
  972. return $message;
  973. }
  974. add_filter('wp_new_user_notification_email', 'new_user_message_fix');
  975. /*
  976. * 评论邮件回复
  977. */
  978. function comment_mail_notify($comment_id)
  979. {
  980. $mail_user_name = iro_opt('mail_user_name') ? iro_opt('mail_user_name') : 'poi';
  981. $comment = get_comment($comment_id);
  982. $parent_id = $comment->comment_parent ?: '';
  983. $spam_confirmed = $comment->comment_approved;
  984. $mail_notify = iro_opt('mail_notify') ? get_comment_meta($parent_id, 'mail_notify', false) : false;
  985. $admin_notify = iro_opt('admin_notify') ? '1' : ((isset(get_comment($parent_id)->comment_author_email) && get_comment($parent_id)->comment_author_email) != get_bloginfo('admin_email') ? '1' : '0');
  986. if (($parent_id != '') && ($spam_confirmed != 'spam') && ($admin_notify != '0') && (!$mail_notify)) {
  987. $wp_email = $mail_user_name . '@' . preg_replace('#^www\.#', '', strtolower($_SERVER['SERVER_NAME']));
  988. $to = trim(get_comment($parent_id)->comment_author_email);
  989. $subject = '你在 [' . get_option("blogname") . '] 的留言有了回应';
  990. $message = '
  991. <div style="background: white;
  992. width: 95%;
  993. max-width: 800px;
  994. margin: auto auto;
  995. border-radius: 5px;
  996. border: ' . iro_opt('theme_skin') . ' 1px solid;
  997. overflow: hidden;
  998. -webkit-box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.12);
  999. box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.18);">
  1000. <header style="overflow: hidden;">
  1001. <img style="width:100%;z-index: 666;" src="' . iro_opt('mail_img') . '">
  1002. </header>
  1003. <div style="padding: 5px 20px;">
  1004. <p style="position: relative;
  1005. color: white;
  1006. float: left;
  1007. z-index: 999;
  1008. background: ' . iro_opt('theme_skin') . ';
  1009. padding: 5px 30px;
  1010. margin: -25px auto 0 ;
  1011. box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.30)">Dear&nbsp;' . trim(get_comment($parent_id)->comment_author) . '</p>
  1012. <br>
  1013. <h3>您有一条来自<a style="text-decoration: none;color: ' . iro_opt('theme_skin') . ' " target="_blank" href="' . home_url() . '/">' . get_option("blogname") . '</a>的回复</h3>
  1014. <br>
  1015. <p style="font-size: 14px;">您在文章《' . get_the_title($comment->comment_post_ID) . '》上发表的评论:</p>
  1016. <div style="border-bottom:#ddd 1px solid;border-left:#ddd 1px solid;padding-bottom:20px;background-color:#eee;margin:15px 0px;padding-left:20px;padding-right:20px;border-top:#ddd 1px solid;border-right:#ddd 1px solid;padding-top:20px">'
  1017. . trim(get_comment($parent_id)->comment_content) . '</div>
  1018. <p style="font-size: 14px;">' . trim($comment->comment_author) . ' 给您的回复如下:</p>
  1019. <div style="border-bottom:#ddd 1px solid;border-left:#ddd 1px solid;padding-bottom:20px;background-color:#eee;margin:15px 0px;padding-left:20px;padding-right:20px;border-top:#ddd 1px solid;border-right:#ddd 1px solid;padding-top:20px">'
  1020. . trim($comment->comment_content) . '</div>
  1021. <div style="text-align: center;">
  1022. <img src="' . iro_opt('vision_resource_basepath', 'https://s.nmxc.ltd/sakurairo_vision/@2.7/') . 'basic/comment-mail.png" alt="hr" style="width:100%;
  1023. margin:5px auto 5px auto;
  1024. display: block;">
  1025. <a style="text-transform: uppercase;
  1026. text-decoration: none;
  1027. font-size: 14px;
  1028. border: 2px solid #6c7575;
  1029. color: #2f3333;
  1030. padding: 10px;
  1031. display: inline-block;
  1032. margin: 10px auto 0; " target="_blank" href="' . htmlspecialchars(get_comment_link($parent_id)) . '">点击查看回复的完整內容</a>
  1033. </div>
  1034. <p style="font-size: 12px;text-align: center;color: #999;">本邮件为系统自动发出,请勿直接回复<br>
  1035. &copy; ' . date('Y') . ' ' . get_option("blogname") . '</p>
  1036. </div>
  1037. </div>
  1038. ';
  1039. $message = convert_smilies($message);
  1040. $message = str_replace('{{', '<img src="' . iro_opt('vision_resource_basepath', 'https://s.nmxc.ltd/sakurairo_vision/@2.7/') . '/smilies/bilipng/emoji_', $message);
  1041. $message = str_replace('}}', '.png" alt="emoji" style="height: 2em; max-height: 2em;">', $message);
  1042. $message = str_replace('{UPLOAD}', 'https://i.loli.net/', $message);
  1043. $message = str_replace('[/img][img]', '[/img^img]', $message);
  1044. $message = str_replace('[img]', '<img src="', $message);
  1045. $message = str_replace('[/img]', '" style="width:80%;display: block;margin-left: auto;margin-right: auto;">', $message);
  1046. $message = str_replace('[/img^img]', '" style="width:80%;display: block;margin-left: auto;margin-right: auto;"><img src="', $message);
  1047. $from = 'From: "' . get_option('blogname') . "\" <$wp_email>";
  1048. $headers = "$from\nContent-Type: text/html; charset=" . get_option('blog_charset') . "\n";
  1049. wp_mail($to, $subject, $message, $headers);
  1050. }
  1051. }
  1052. add_action('comment_post', 'comment_mail_notify');
  1053. /*
  1054. * 链接新窗口打开
  1055. */
  1056. function rt_add_link_target($content)
  1057. {
  1058. $content = str_replace('<a', '<a rel="nofollow"', $content);
  1059. // use the <a> tag to split into segments
  1060. $bits = explode('<a ', $content);
  1061. // loop though the segments
  1062. foreach ($bits as $key => $bit) {
  1063. // fix the target="_blank" bug after the link
  1064. if (strpos($bit, 'href') === false) {
  1065. continue;
  1066. }
  1067. // fix the target="_blank" bug in the codeblock
  1068. if (strpos(preg_replace('/code([\s\S]*?)\/code[\s]*/m', 'temp', $content), $bit) === false) {
  1069. continue;
  1070. }
  1071. // find the end of each link
  1072. $pos = strpos($bit, '>');
  1073. // check if there is an end (only fails with malformed markup)
  1074. if ($pos !== false) {
  1075. // get a string with just the link's attibutes
  1076. $part = substr($bit, 0, $pos);
  1077. // for comparison, get the current site/network url
  1078. $siteurl = network_site_url();
  1079. // if the site url is in the attributes, assume it's in the href and skip, also if a target is present
  1080. if (strpos($part, $siteurl) === false && strpos($part, 'target=') === false) {
  1081. // add the target attribute
  1082. $bits[$key] = 'target="_blank" ' . $bits[$key];
  1083. }
  1084. }
  1085. }
  1086. // re-assemble the content, and return it
  1087. return implode('<a ', $bits);
  1088. }
  1089. add_filter('comment_text', 'rt_add_link_target');
  1090. // 评论通过BBCode插入图片
  1091. function comment_picture_support($content)
  1092. {
  1093. $content = str_replace('http://', 'https://', $content); // 干掉任何可能的 http
  1094. $content = str_replace('{UPLOAD}', 'https://i.loli.net/', $content);
  1095. $content = str_replace('[/img][img]', '[/img^img]', $content);
  1096. $content = str_replace('[img]', '<br><img src="' . iro_opt('load_in_svg') . '" data-src="', $content);
  1097. $content = str_replace('[/img]', '" class="lazyload comment_inline_img" onerror="imgError(this)"><br>', $content);
  1098. $content = str_replace('[/img^img]', '" class="lazyload comment_inline_img" onerror="imgError(this)"><img src="' . iro_opt('load_in_svg') . '" data-src="', $content);
  1099. return $content;
  1100. }
  1101. add_filter('comment_text', 'comment_picture_support');
  1102. /*
  1103. * 修改评论表情调用路径
  1104. */
  1105. // 简单遍历系统表情库,今后应考虑标识表情包名——使用增加的扩展名,同时保留原有拓展名
  1106. // 还有一个思路是根据表情调用路径来判定<-- 此法最好!
  1107. // 贴吧
  1108. function make_onclick_grin($name,$type,$before='',$after=''){
  1109. $extra_params = "";
  1110. if($before || $after){
  1111. $extra_params = ",'$before','$after'";
  1112. }
  1113. return "onclick=\"grin('$name','$type'$extra_params)\"";
  1114. }
  1115. /**
  1116. * 通过文件夹获取自定义表情列表,使用Transients来存储获得的列表,除非手动清除,数据永不过期。
  1117. * 数据格式如下:
  1118. * Array
  1119. * (
  1120. * [0] => Array
  1121. * (
  1122. * [path] => C:\xampp\htdocs\wordpress/wp-content/uploads/sakurairo_vision/@2.4/smilies\bilipng\emoji_2233_chijing.png
  1123. * [little_path] => /sakurairo_vision/@2.4/smilies\bilipng\emoji_2233_chijing.png
  1124. * [file_url] => http://192.168.233.174/wordpress/wp-content/uploads/sakurairo_vision/@2.4/smilies\bilipng\emoji_2233_chijing.png
  1125. * [name] => emoji_2233_chijing.png
  1126. * [base_name] => emoji_2233_chijing
  1127. * [extension] => png
  1128. * )
  1129. * ...
  1130. * )
  1131. *
  1132. * @return array
  1133. */
  1134. function get_custom_smilies_list()
  1135. {
  1136. $custom_smilies_list = get_transient("custom_smilies_list");
  1137. if ($custom_smilies_list !== false) {
  1138. return $custom_smilies_list;
  1139. }
  1140. $custom_smilies_list = array();
  1141. $custom_smilies_dir = iro_opt('smilies_dir');
  1142. if (!$custom_smilies_dir) {
  1143. return $custom_smilies_list;
  1144. }
  1145. $custom_smilies_extension = ['jpg', 'jpeg', 'png', 'gif', 'svg', 'avif', 'webp'];
  1146. $custom_smilies_path = wp_get_upload_dir()['basedir'] . $custom_smilies_dir;
  1147. if (!is_dir($custom_smilies_path)) {
  1148. return $custom_smilies_list;
  1149. }
  1150. $files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($custom_smilies_path), RecursiveIteratorIterator::LEAVES_ONLY);
  1151. foreach ($files as $file) {
  1152. if ($file->isFile()) {
  1153. $file_name = $file->getFilename();
  1154. $file_base_name = pathinfo($file_name, PATHINFO_FILENAME);
  1155. $file_extension = pathinfo($file_name, PATHINFO_EXTENSION);
  1156. $file_path = $file->getPathname();
  1157. $file_little_path = str_replace(wp_get_upload_dir()['basedir'], '', $file_path);
  1158. $file_url = wp_get_upload_dir()['baseurl'] . $file_little_path;
  1159. if (in_array($file_extension, $custom_smilies_extension)) {
  1160. $custom_smilies_list[] = array(
  1161. 'path' => $file_path,
  1162. 'little_path' => $file_little_path,
  1163. 'file_url' => $file_url,
  1164. 'name' => $file_name,
  1165. 'base_name' => $file_base_name,
  1166. 'extension' => $file_extension
  1167. );
  1168. }
  1169. }
  1170. }
  1171. set_transient("custom_smilies_list", $custom_smilies_list);
  1172. return $custom_smilies_list;
  1173. }
  1174. /**
  1175. * 通过 GET 方法更新自定义表情包列表
  1176. */
  1177. function update_custom_smilies_list()
  1178. {
  1179. if (!is_admin() || !current_user_can('manage_options')) {
  1180. return;
  1181. }
  1182. if (!isset($_GET['update_custom_smilies'])) {
  1183. return;
  1184. }
  1185. $transient_name = sanitize_key($_GET['update_custom_smilies']);
  1186. if ($transient_name === 'true') {
  1187. delete_transient("custom_smilies_list");
  1188. $custom_smilies_list = get_custom_smilies_list();
  1189. $much = count($custom_smilies_list);
  1190. echo '自定义表情列表更新完成!总共有' . $much . '个表情。';
  1191. }
  1192. }
  1193. update_custom_smilies_list();
  1194. $custom_smiliestrans = array();
  1195. /**
  1196. * 输出表情列表
  1197. *
  1198. */
  1199. function push_custom_smilies()
  1200. {
  1201. global $custom_smiliestrans;
  1202. $custom_smilies_panel = '';
  1203. $custom_smilies_list = get_custom_smilies_list();
  1204. if (!$custom_smilies_list) {
  1205. $custom_smilies_panel = '<div style="font-size: 20px;text-align: center;width: 300px;height: 100px;line-height: 100px;">File does not exist!</div>';
  1206. return $custom_smilies_panel;
  1207. }
  1208. $custom_smilies_cdn = iro_opt('smilies_proxy');
  1209. foreach ($custom_smilies_list as $smiley) {
  1210. if ($custom_smilies_cdn) {
  1211. $smiley_url = $custom_smilies_cdn . $smiley['little_path'];
  1212. } else {
  1213. $smiley_url = $smiley['file_url'];
  1214. }
  1215. $custom_smilies_panel = $custom_smilies_panel . '<span title="' . $smiley['base_name'].'" ' . make_onclick_grin($smiley['base_name'],'Math').'><img alt="custom_smilies" loading="lazy" style="height: 60px;" src="' . $smiley_url . '" /></span>';
  1216. $custom_smiliestrans['{{' . $smiley['base_name'] . '}}'] = '<span title="' . $smiley['base_name'] . '" ><img alt="custom_smilies" loading="lazy" style="height: 60px;" src="' . $smiley_url . '" /></span>';
  1217. }
  1218. return $custom_smilies_panel;
  1219. }
  1220. /**
  1221. * 替换评论、文章中的表情符号
  1222. *
  1223. */
  1224. function custom_smilies_filter($content)
  1225. {
  1226. push_custom_smilies();
  1227. global $custom_smiliestrans;
  1228. $content = str_replace(array_keys($custom_smiliestrans), $custom_smiliestrans, $content);
  1229. return $content;
  1230. }
  1231. add_filter('the_content', 'custom_smilies_filter');
  1232. add_filter('comment_text', 'custom_smilies_filter');
  1233. $wpsmiliestrans = array();
  1234. function push_tieba_smilies()
  1235. {
  1236. global $wpsmiliestrans;
  1237. // don't bother setting up smilies if they are disabled
  1238. if (!get_option('use_smilies'))
  1239. return;
  1240. $tiebaname = array('good', 'han', 'spray', 'Grievance', 'shui', 'reluctantly', 'anger', 'tongue', 'se', 'haha', 'rmb', 'doubt', 'tear', 'surprised2', 'Happy', 'ku', 'surprised', 'theblackline', 'smilingeyes', 'spit', 'huaji', 'bbd', 'hu', 'shame', 'naive', 'rbq', 'britan', 'aa', 'niconiconi', 'niconiconi_t', 'niconiconit', 'awesome');
  1241. $return_smiles = '';
  1242. $type = is_webp() ? 'webp' : 'png';
  1243. $tiebaimgdir = 'tieba' . $type . '/';
  1244. $smiliesgs = '.' . $type;
  1245. foreach ($tiebaname as $tieba_Name) {
  1246. $grin = make_onclick_grin($tieba_Name,'tieba');
  1247. // 选择面版
  1248. $return_smiles = $return_smiles . '<span title="' . $tieba_Name . '" '.$grin.'><img alt="tieba_smilie" loading="lazy" src="' . iro_opt('vision_resource_basepath', 'https://s.nmxc.ltd/sakurairo_vision/@2.7/') . 'smilies/' . $tiebaimgdir . 'icon_' . $tieba_Name . $smiliesgs . '" /></span>';
  1249. // 正文转换
  1250. $wpsmiliestrans['::' . $tieba_Name . '::'] = '<span title="' . $tieba_Name . '" '.$grin.'><img alt="tieba_smilie" loading="lazy" src="' . iro_opt('vision_resource_basepath', 'https://s.nmxc.ltd/sakurairo_vision/@2.7/') . 'smilies/' . $tiebaimgdir . 'icon_' . $tieba_Name . $smiliesgs . '" /></span>';
  1251. }
  1252. return $return_smiles;
  1253. }
  1254. push_tieba_smilies();
  1255. function tieba_smile_filter($content)
  1256. {
  1257. global $wpsmiliestrans;
  1258. $content = str_replace(array_keys($wpsmiliestrans), $wpsmiliestrans, $content);
  1259. return $content;
  1260. }
  1261. add_filter('the_content', 'tieba_smile_filter'); //替换文章关键词
  1262. add_filter('comment_text', 'tieba_smile_filter'); //替换评论关键词
  1263. function push_emoji_panel()
  1264. {
  1265. $emojis = ['(⌒▽⌒)', '( ̄▽ ̄)', '(=・ω・=)', '(`・ω・´)', '(〜 ̄△ ̄)〜', '(・∀・)', '(°∀°)ノ', '( ̄3 ̄)', '╮( ̄▽ ̄)╭', '(´_ゝ`)', '←_←', '→_→', '(&lt;_&lt;)', '(&gt;_&gt;)', '(;¬_¬)', '("▔□▔)/', '(゚Д゚≡゚д゚)!?', 'Σ(゚д゚;)', 'Σ( ̄□ ̄||)', '(’;ω;‘)', '(/TДT)/', '(^・ω・^ )', '(。・ω・。)', '(● ̄(エ) ̄●)', 'ε=ε=(ノ≧∇≦)ノ', '(’・_・‘)', '(-_-#)', '( ̄へ ̄)', '( ̄ε(# ̄)Σ', 'ヽ(‘Д’)ノ', '(#-_-)┯━┯', '(╯°口°)╯(┴—┴', '←◡←', '( ♥д♥)', '_(:3」∠)_', 'Σ&gt;―(〃°ω°〃)♡→', '⁄(⁄ ⁄•⁄ω⁄•⁄ ⁄)⁄', '(╬゚д゚)▄︻┻┳═一', '・*・:≡( ε:)', '(笑)', '(汗)', '(泣)', '(苦笑)'];
  1266. return join('', array_map(function ($emoji) {
  1267. return '<a class="emoji-item">' . $emoji . '</a>';
  1268. }, $emojis));
  1269. }
  1270. // bilibili smiles
  1271. $bilismiliestrans = array();
  1272. function push_bili_smilies()
  1273. {
  1274. global $bilismiliestrans;
  1275. $name = array('baiyan', 'bishi', 'bizui', 'chan', 'dai', 'daku', 'dalao', 'dalian', 'dianzan', 'doge', 'facai', 'fanu', 'ganga', 'guilian', 'guzhang', 'haixiu', 'heirenwenhao', 'huaixiao', 'jingxia', 'keai', 'koubizi', 'kun', 'lengmo', 'liubixue', 'liuhan', 'liulei', 'miantian', 'mudengkoudai', 'nanguo', 'outu', 'qinqin', 'se', 'shengbing', 'shengqi', 'shuizhao', 'sikao', 'tiaokan', 'tiaopi', 'touxiao', 'tuxue', 'weiqu', 'weixiao', 'wunai', 'xiaoku', 'xieyanxiao', 'yiwen', 'yun', 'zaijian', 'zhoumei', 'zhuakuang');
  1276. $return_smiles = '';
  1277. $type = is_webp() ? 'webp' : 'png';
  1278. $biliimgdir = 'bili' . $type . '/';
  1279. $smiliesgs = '.' . $type;
  1280. foreach ($name as $smilies_Name) {
  1281. $grin = make_onclick_grin($smilies_Name,'Math');
  1282. // 选择面版
  1283. $return_smiles = $return_smiles . '<span title="' . $smilies_Name . '" '.$grin.'><img alt="bili_smilies" loading="lazy" src="' . iro_opt('vision_resource_basepath', 'https://s.nmxc.ltd/sakurairo_vision/@2.7/') . 'smilies/' . $biliimgdir . 'emoji_' . $smilies_Name . $smiliesgs . '" /></span>';
  1284. // 正文转换
  1285. $bilismiliestrans['{{' . $smilies_Name . '}}'] = '<span title="' . $smilies_Name . '" '.$grin.'><img alt="bili_smilies" loading="lazy" src="' . iro_opt('vision_resource_basepath', 'https://s.nmxc.ltd/sakurairo_vision/@2.7/') . 'smilies/' . $biliimgdir . 'emoji_' . $smilies_Name . $smiliesgs . '" /></span>';
  1286. }
  1287. return $return_smiles;
  1288. }
  1289. push_bili_smilies();
  1290. function bili_smile_filter($content)
  1291. {
  1292. global $bilismiliestrans;
  1293. $content = str_replace(array_keys($bilismiliestrans), $bilismiliestrans, $content);
  1294. return $content;
  1295. }
  1296. add_filter('the_content', 'bili_smile_filter'); //替换文章关键词
  1297. add_filter('comment_text', 'bili_smile_filter'); //替换评论关键词
  1298. function featuredtoRSS($content)
  1299. {
  1300. global $post;
  1301. if (has_post_thumbnail($post->ID)) {
  1302. $content = '<div>' . get_the_post_thumbnail($post->ID, 'medium', array('style' => 'margin-bottom: 15px;')) . '</div>' . $content;
  1303. }
  1304. return $content;
  1305. }
  1306. add_filter('the_excerpt_rss', 'featuredtoRSS');
  1307. add_filter('the_content_feed', 'featuredtoRSS');
  1308. //
  1309. function bili_smile_filter_rss($content)
  1310. {
  1311. $type = is_webp() ? 'webp' : 'png';
  1312. $biliimgdir = 'bili' . $type . '/';
  1313. $smiliesgs = '.' . $type;
  1314. $content = str_replace('{{', '<img src="' . iro_opt('vision_resource_basepath', 'https://s.nmxc.ltd/sakurairo_vision/@2.7/') . 'smilies/' . $biliimgdir, $content);
  1315. $content = str_replace('}}', $smiliesgs . '" alt="emoji" style="height: 2em; max-height: 2em;">', $content);
  1316. $content = str_replace('[img]', '<img src="', $content);
  1317. $content = str_replace('[/img]', '" style="display: block;margin-left: auto;margin-right: auto;">', $content);
  1318. return $content;
  1319. }
  1320. add_filter('comment_text_rss', 'bili_smile_filter_rss'); //替换评论rss关键词
  1321. function toc_support($content)
  1322. {
  1323. $content = str_replace('[toc]', '<div class="has-toc have-toc"></div>', $content); // TOC 支持
  1324. $content = str_replace('[begin]', '<span class="begin">', $content); // 首字格式支持
  1325. $content = str_replace('[/begin]', '</span>', $content); // 首字格式支持
  1326. return $content;
  1327. }
  1328. add_filter('the_content', 'toc_support');
  1329. add_filter('the_excerpt_rss', 'toc_support');
  1330. add_filter('the_content_feed', 'toc_support');
  1331. function check_title_tags($content)
  1332. {
  1333. if (!empty($content)) {
  1334. $dom = new DOMDocument();
  1335. @$dom->loadHTML($content);
  1336. $headings = $dom->getElementsByTagName('h1');
  1337. for ($i = 1; $i <= 6; $i++) {
  1338. $headings = $dom->getElementsByTagName('h' . $i);
  1339. foreach ($headings as $heading) {
  1340. if (trim($heading->nodeValue) != '') {
  1341. return true;
  1342. }
  1343. }
  1344. }
  1345. }
  1346. return false;
  1347. }
  1348. // 显示访客当前 IP
  1349. function get_the_user_ip()
  1350. {
  1351. // if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
  1352. // //check ip from share internet
  1353. // $ip = $_SERVER['HTTP_CLIENT_IP'];
  1354. // } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
  1355. // //to check ip is pass from proxy
  1356. // $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
  1357. // } else {
  1358. // $ip = $_SERVER['REMOTE_ADDR'];
  1359. // }
  1360. // 简略版
  1361. // $ip = $_SERVER['HTTP_CLIENT_IP'] ?: ($_SERVER['HTTP_X_FORWARDED_FOR'] ?: $_SERVER['REMOTE_ADDR']);
  1362. $ip = $_SERVER['HTTP_CLIENT_IP'] ?? $_SERVER['HTTP_X_FORWARDED_FOR'] ?? $_SERVER['REMOTE_ADDR'];
  1363. return apply_filters('wpb_get_ip', $ip);
  1364. }
  1365. add_shortcode('show_ip', 'get_the_user_ip');
  1366. /*歌词*/
  1367. function hero_get_lyric()
  1368. {
  1369. /** These are the lyrics to Hero */
  1370. $lyrics = "";
  1371. // Here we split it into lines
  1372. $lyrics = explode("\n", $lyrics);
  1373. // And then randomly choose a line
  1374. return wptexturize($lyrics[mt_rand(0, count($lyrics) - 1)]);
  1375. }
  1376. // This just echoes the chosen line, we'll position it later
  1377. function hello_hero()
  1378. {
  1379. $chosen = hero_get_lyric();
  1380. echo $chosen;
  1381. }
  1382. /*私密评论*/
  1383. add_action('wp_ajax_nopriv_siren_private', 'siren_private');
  1384. add_action('wp_ajax_siren_private', 'siren_private');
  1385. function siren_private()
  1386. {
  1387. $comment_id = $_POST["p_id"];
  1388. $action = $_POST["p_action"];
  1389. if ($action == 'set_private') {
  1390. update_comment_meta($comment_id, '_private', 'true');
  1391. $i_private = get_comment_meta($comment_id, '_private', true);
  1392. echo empty($i_private) ? '是' : '否';
  1393. }
  1394. die;
  1395. }
  1396. //时间序列
  1397. function memory_archives_list()
  1398. {
  1399. // 尝试从缓存中获取结果
  1400. $cache_key = 'memory_archives_list_' . get_locale();
  1401. $output = get_transient($cache_key);
  1402. if ($output !== false) {
  1403. echo $output;
  1404. return;
  1405. }
  1406. $output = '<div id="archives"><p style="text-align:right;">[<span id="al_expand_collapse">' . __("All expand/collapse", "sakurairo") /*全部展开/收缩*/. '</span>]<!-- (注: 点击月份可以展开)--></p>';
  1407. $posts = get_posts(
  1408. array(
  1409. 'posts_per_page' => -1,
  1410. 'ignore_sticky_posts' => true,
  1411. 'post_type' => 'post'
  1412. )
  1413. );
  1414. $posts_sorted_by_time = [];
  1415. foreach ($posts as $post) {
  1416. $post_id = $post->ID;
  1417. $post_time = get_post_time('U', false, $post_id);
  1418. $posts_sorted_by_time[$post_time] = $post;
  1419. }
  1420. krsort($posts_sorted_by_time); // 按时间倒序排列
  1421. $year = 0;
  1422. $mon = 0;
  1423. foreach ($posts_sorted_by_time as $post) {
  1424. setup_postdata($post);
  1425. $year_tmp = get_post_time('Y', false, $post);
  1426. $mon_tmp = get_post_time('m', false, $post);
  1427. $post_id = $post->ID;
  1428. $post_views = get_post_views($post_id);
  1429. if ($mon != $mon_tmp && $mon > 0) {
  1430. $output .= '</ul></li>';
  1431. }
  1432. if ($year != $year_tmp && $year > 0) {
  1433. $output .= '</ul>';
  1434. }
  1435. if ($year != $year_tmp) {
  1436. $year = $year_tmp;
  1437. $output .= '<h3 class="al_year">' . $year . __(" year", "sakurairo") . /*年*/' </h3><ul class="al_mon_list">'; //输出年份
  1438. }
  1439. if ($mon != $mon_tmp) {
  1440. $mon = $mon_tmp;
  1441. $output .= '<li class="al_li"><span class="al_mon"><span style="color:' . iro_opt('theme_skin') . ';">' . get_post_time('M', false, $post) . '</span> (<span id="post-num"></span>' . __(" post(s)", "sakurairo") /*篇文章*/. ')</span><ul class="al_post_list">'; //输出月份
  1442. }
  1443. $output .= '<li>' . '<a href="' . get_permalink($post) . '"><span style="color:' . iro_opt('theme_skin') . ';">' /*get_post_time('d'.__(" ","sakurairo"), false, $post) 日*/. '</span>' . get_the_title($post) . ' <span>(' . $post_views . ' <span class="fa-solid fa-chess-queen" aria-hidden="true"></span> / ' . get_comments_number($post) . ' <span class="fa-regular fa-comment-dots" aria-hidden="true"></span>)</span></a></li>';
  1444. }
  1445. wp_reset_postdata();
  1446. $output .= '</ul></li></ul> <!--<ul class="al_mon_list"><li><ul class="al_post_list" style="display: block;"><li>博客已经萌萌哒运行了<span id="monitorday"></span>天</li></ul></li></ul>--></div>';
  1447. set_transient($cache_key, $output, 3600);
  1448. echo $output;
  1449. }
  1450. // 在保存文章后清空缓存
  1451. function clear_memory_archives_list_cache($post_id)
  1452. {
  1453. delete_transient('memory_archives_list_' . get_locale());
  1454. }
  1455. add_action('save_post', 'clear_memory_archives_list_cache');
  1456. require_once __DIR__ . '/inc/word-stat.php';
  1457. /**
  1458. * 字数、词数统计
  1459. */
  1460. function count_post_words($post_ID)
  1461. {
  1462. $post = get_post($post_ID);
  1463. if ($post->post_type !== "post") {
  1464. return;
  1465. }
  1466. $content = $post->post_content;
  1467. $content = strip_tags($content);
  1468. $count = word_stat($content);
  1469. update_post_meta($post_ID, 'post_words_count', $count);
  1470. return $count;
  1471. }
  1472. add_action('save_post', 'count_post_words');
  1473. /*
  1474. * 隐藏 Dashboard
  1475. */
  1476. /* Remove the "Dashboard" from the admin menu for non-admin users */
  1477. function remove_dashboard()
  1478. {
  1479. global $current_user, $menu, $submenu;
  1480. wp_get_current_user();
  1481. if (!in_array('administrator', $current_user->roles)) {
  1482. reset($menu);
  1483. $page = key($menu);
  1484. while ((__('Dashboard') != $menu[$page][0]) && next($menu)) {
  1485. $page = key($menu);
  1486. }
  1487. if (__('Dashboard') == $menu[$page][0]) {
  1488. unset($menu[$page]);
  1489. }
  1490. reset($menu);
  1491. $page = key($menu);
  1492. while (!$current_user->has_cap($menu[$page][1]) && next($menu)) {
  1493. $page = key($menu);
  1494. }
  1495. if (
  1496. preg_match('#wp-admin/?(index.php)?$#', $_SERVER['REQUEST_URI']) &&
  1497. ('index.php' != $menu[$page][2])
  1498. ) {
  1499. wp_redirect(get_option('siteurl') . '/wp-admin/profile.php');
  1500. }
  1501. }
  1502. }
  1503. add_action('admin_menu', 'remove_dashboard');
  1504. /**
  1505. * Filter the except length to 20 words. 限制摘要长度
  1506. *
  1507. * @param int $length Excerpt length.
  1508. * @return int (Maybe) modified excerpt length.
  1509. */
  1510. function GBsubstr($string, $start, $length)
  1511. {
  1512. if (strlen($string) > $length) {
  1513. $str = null;
  1514. $len = 0;
  1515. $i = $start;
  1516. while ($len < $length) {
  1517. if (ord(substr($string, $i, 1)) > 0xc0) {
  1518. $str .= substr($string, $i, 3);
  1519. $i += 3;
  1520. } elseif (ord(substr($string, $i, 1)) > 0xa0) {
  1521. $str .= substr($string, $i, 2);
  1522. $i += 2;
  1523. } else {
  1524. $str .= substr($string, $i, 1);
  1525. $i++;
  1526. }
  1527. $len++;
  1528. }
  1529. return $str;
  1530. } else {
  1531. return $string;
  1532. }
  1533. }
  1534. /**
  1535. * chatgpt excerpt
  1536. */
  1537. require_once __DIR__ . '/inc/chatgpt/hooks.php';
  1538. IROChatGPT\apply_chatgpt_hook();
  1539. function excerpt_length($exp)
  1540. {
  1541. if (!function_exists('mb_substr')) {
  1542. $exp = GBsubstr($exp, 0, 110);
  1543. } else {
  1544. /*
  1545. * To use mb_substr() function, you should uncomment "extension=php_mbstring.dll" in php.ini
  1546. */
  1547. $exp = mb_substr($exp, 0, 110);
  1548. }
  1549. return $exp;
  1550. }
  1551. add_filter('the_excerpt', 'excerpt_length', 11);
  1552. /*
  1553. * 后台路径
  1554. */
  1555. /*
  1556. add_filter('site_url', 'wpadmin_filter', 10, 3);
  1557. function wpadmin_filter( $url, $path, $orig_scheme ) {
  1558. $old = array( "/(wp-admin)/");
  1559. $admin_dir = WP_ADMIN_DIR;
  1560. $new = array($admin_dir);
  1561. return preg_replace( $old, $new, $url, 1);
  1562. }
  1563. */
  1564. function admin_ini()
  1565. {
  1566. wp_enqueue_style('admin-styles-fix-icon', get_site_url() . '/wp-includes/css/dashicons.css');
  1567. wp_enqueue_style('cus-styles-fit', get_template_directory_uri() . '/css/dashboard-fix.css');
  1568. }
  1569. add_action('admin_enqueue_scripts', 'admin_ini');
  1570. /*
  1571. * 后台通知
  1572. */
  1573. /**
  1574. * 在提供权限的情况下,为管理员用户显示通知并更新 meta 值
  1575. */
  1576. function theme_admin_notice_callback()
  1577. {
  1578. // 判断当前用户是否为管理员
  1579. if (!current_user_can('manage_options')) {
  1580. return;
  1581. }
  1582. // 读取 meta 值
  1583. $meta_value = get_user_meta(get_current_user_id(), 'theme_admin_notice', true);
  1584. // 判断 meta 值是否存在
  1585. if ($meta_value) {
  1586. return; // 如果存在,退出函数,避免重复加载通知
  1587. }
  1588. // 显示通知
  1589. $theme_name = 'Sakurairo';
  1590. switch (get_locale()) {
  1591. case 'zh_CN':
  1592. $thankyou = '感谢你使用 ' . $theme_name . ' 主题!这里有一些需要你的许可的东西(*/ω\*)';
  1593. $dislike = '不,谢谢';
  1594. $allow_send = '允许发送你的主题版本数据以便官方统计';
  1595. break;
  1596. case 'zh_TW':
  1597. $thankyou = '感謝你使用 ' . $theme_name . ' 主題!以下是一些需要你許可的內容。';
  1598. $dislike = '謝謝,不用了';
  1599. $allow_send = '允許出於統計目的發送主題版本数据';
  1600. break;
  1601. case 'ja':
  1602. $thankyou = 'ご使用いただきありがとうございます!以下は、あなたの許可が必要なコンテンツです。';
  1603. $dislike = 'いいえ、結構です';
  1604. $allow_send = '統計目的のためにあなたのテーマバージョンを送信することを許可する';
  1605. break;
  1606. default:
  1607. $thankyou = 'Thank you for using the ' . $theme_name . ' theme! There is something that needs your approval.';
  1608. $dislike = 'No, thanks';
  1609. $allow_send = 'Allow sending your theme version for statistical purposes';
  1610. break;
  1611. }
  1612. ?>
  1613. <div class="notice notice-success" id="send-ver-tip">
  1614. <p><?php echo $thankyou; ?></p>
  1615. <button class="button" onclick="dismiss_notice()"><?php echo $dislike; ?></button>
  1616. <button class="button" onclick="update_option()"><?php echo $allow_send; ?></button>
  1617. </div>
  1618. <script>
  1619. function dismiss_notice() {
  1620. // 隐藏通知
  1621. document.getElementById( "send-ver-tip" ).style.display = "none";
  1622. // 写入 1 到 meta
  1623. var data = new FormData();
  1624. data.append( 'action', 'update_theme_admin_notice_meta' );
  1625. data.append( 'user_id', '<?php echo get_current_user_id(); ?>' );
  1626. data.append( 'meta_key', 'theme_admin_notice' );
  1627. data.append( 'meta_value', '1' );
  1628. fetch( '<?php echo admin_url('admin-ajax.php'); ?>', {
  1629. method: 'POST',
  1630. body: data
  1631. } );
  1632. }
  1633. function update_option() {
  1634. // 隐藏通知
  1635. document.getElementById( "send-ver-tip" ).style.display = "none";
  1636. // 发送 AJAX 请求
  1637. var xhr = new XMLHttpRequest();
  1638. xhr.open( "POST", "<?php echo admin_url('admin-ajax.php'); ?>", true );
  1639. xhr.setRequestHeader( "Content-Type", "application/x-www-form-urlencoded" );
  1640. xhr.send( "action=update_theme_option&option=send_theme_version&value=true" );
  1641. // 写入 1 到 meta
  1642. var data = new FormData();
  1643. data.append( 'action', 'update_theme_admin_notice_meta' );
  1644. data.append( 'user_id', '<?php echo get_current_user_id(); ?>' );
  1645. data.append( 'meta_key', 'theme_admin_notice' );
  1646. data.append( 'meta_value', '1' );
  1647. fetch( '<?php echo admin_url('admin-ajax.php'); ?>', {
  1648. method: 'POST',
  1649. body: data
  1650. } );
  1651. }
  1652. </script>
  1653. <?php
  1654. }
  1655. add_action('admin_notices', 'theme_admin_notice_callback');
  1656. // AJAX 处理函数 - 更新主题选项
  1657. add_action('wp_ajax_update_theme_option', 'update_theme_option');
  1658. function update_theme_option()
  1659. {
  1660. $option = $_POST['option'];
  1661. $value = sanitize_text_field($_POST['value']);
  1662. iro_opt_update($option, $value);
  1663. wp_die();
  1664. }
  1665. // AJAX 处理函数 - 写入 theme_admin_notice 元值
  1666. add_action('wp_ajax_update_theme_admin_notice_meta', 'update_theme_admin_notice_meta');
  1667. function update_theme_admin_notice_meta()
  1668. {
  1669. $user_id = $_POST['user_id'];
  1670. $meta_key = $_POST['meta_key'];
  1671. $meta_value = sanitize_text_field($_POST['meta_value']);
  1672. update_user_meta($user_id, $meta_key, $meta_value);
  1673. wp_die();
  1674. }
  1675. //dashboard scheme
  1676. function dash_scheme($key, $name, $col1, $col2, $col3, $col4, $base, $focus, $current, $rules = "")
  1677. {
  1678. $hash = 'rules=' . urlencode($rules);
  1679. if ($col1) {
  1680. $hash .= '&color_1=' . str_replace("#", "", $col1);
  1681. }
  1682. if ($col2) {
  1683. $hash .= '&color_2=' . str_replace("#", "", $col2);
  1684. }
  1685. if ($col3) {
  1686. $hash .= '&color_3=' . str_replace("#", "", $col3);
  1687. }
  1688. if ($col4) {
  1689. $hash .= '&color_4=' . str_replace("#", "", $col4);
  1690. }
  1691. wp_admin_css_color(
  1692. $key,
  1693. $name,
  1694. get_template_directory_uri() . "/inc/dash-scheme.php?" . $hash,
  1695. array($col1, $col2, $col3, $col4),
  1696. array('base' => $base, 'focus' => $focus, 'current' => $current)
  1697. );
  1698. }
  1699. //Sakurairo
  1700. dash_scheme(
  1701. $key = "sakurairo",
  1702. $name = "Sakurairo🌸",
  1703. $col1 = iro_opt('admin_second_class_color'),
  1704. $col2 = iro_opt('admin_first_class_color'),
  1705. $col3 = iro_opt('admin_emphasize_color'),
  1706. $col4 = iro_opt('admin_emphasize_color'),
  1707. $base = "#FFF",
  1708. $focus = "#FFF",
  1709. $current = "#FFF",
  1710. $rules = '#adminmenu .wp-has-current-submenu .wp-submenu a,#adminmenu .wp-has-current-submenu.opensub .wp-submenu a,#adminmenu .wp-submenu a,#adminmenu a.wp-has-current-submenu:focus+.wp-submenu a,#wpadminbar .ab-submenu .ab-item,#wpadminbar .quicklinks .menupop ul li a,#wpadminbar .quicklinks .menupop.hover ul li a,#wpadminbar.nojs .quicklinks .menupop:hover ul li a, .csf-field-button_set .csf--active, .csf-field-button_set .csf--active:hover, .folded #adminmenu .wp-has-current-submenu .wp-submenu a{color:' . iro_opt('admin_text_color') . '}body{background-image:url(' . iro_opt('admin_background') . ');background-attachment:fixed;background-size:cover;}#wpcontent{background:rgba(255,255,255,.0)}.wp-core-ui .button-primary{background:' . iro_opt('admin_button_color') . '!important;border-color:' . iro_opt('admin_button_color') . '!important;color:' . iro_opt('admin_text_color') . '!important;box-shadow:0 1px 0 ' . iro_opt('admin_button_color') . '!important;text-shadow:0 -1px 1px ' . iro_opt('admin_button_color') . ',1px 0 1px ' . iro_opt('admin_button_color') . ',0 1px 1px ' . iro_opt('admin_button_color') . ',-1px 0 1px ' . iro_opt('admin_button_color') . '!important}'
  1711. );
  1712. //Set Default Admin Color Scheme for New Users
  1713. function set_default_admin_color($user_id)
  1714. {
  1715. $args = array(
  1716. 'ID' => $user_id,
  1717. 'admin_color' => 'sunrise',
  1718. );
  1719. wp_update_user($args);
  1720. }
  1721. //add_action('user_register', 'set_default_admin_color');
  1722. //Stop Users From Switching Admin Color Schemes
  1723. //if ( !current_user_can('manage_options') ) remove_action( 'admin_color_scheme_picker', 'admin_color_scheme_picker' );
  1724. // WordPress Custom style @ Admin
  1725. function custom_admin_open_sans_style()
  1726. {
  1727. require get_template_directory() . '/inc/admin_addcss.php';
  1728. }
  1729. add_action('admin_head', 'custom_admin_open_sans_style');
  1730. // WordPress Custom Font @ Admin
  1731. function custom_admin_open_sans_font()
  1732. {
  1733. echo '<link href="https://' . iro_opt('gfonts_api', 'fonts.googleapis.com') . '/css?family=Noto+Serif+SC&display=swap" rel="stylesheet">' . PHP_EOL;
  1734. echo '<style>body, #wpadminbar *:not([class="ab-icon"]), .wp-core-ui, .media-menu, .media-frame *, .media-modal *{font-family: "Noto Serif SC", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif !important;}</style>' . PHP_EOL;
  1735. }
  1736. add_action('admin_head', 'custom_admin_open_sans_font');
  1737. // WordPress Custom Font @ Admin Frontend Toolbar
  1738. function custom_admin_open_sans_font_frontend_toolbar()
  1739. {
  1740. if (current_user_can('administrator') && is_admin_bar_showing()) {
  1741. echo '<link href="https://' . iro_opt('gfonts_api', 'fonts.googleapis.com') . '/css?family=Noto+Serif+SC&display=swap" rel="stylesheet">' . PHP_EOL;
  1742. echo '<style>#wpadminbar *:not([class="ab-icon"]){font-family: "Noto Serif SC", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif !important;}</style>' . PHP_EOL;
  1743. }
  1744. }
  1745. add_action('wp_head', 'custom_admin_open_sans_font_frontend_toolbar');
  1746. // WordPress Custom Font @ Admin Login
  1747. function custom_admin_open_sans_font_login_page()
  1748. {
  1749. if (stripos($_SERVER["SCRIPT_NAME"], strrchr(wp_login_url(), '/')) !== false) {
  1750. echo '<link href="https://' . iro_opt('gfonts_api', 'fonts.googleapis.com') . '/css?family=Noto+Serif+SC&display=swap" rel="stylesheet">' . PHP_EOL;
  1751. echo '<style>body{font-family: "Noto Serif SC", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif !important;}</style>' . PHP_EOL;
  1752. }
  1753. }
  1754. add_action('login_head', 'custom_admin_open_sans_font_login_page');
  1755. // 阻止垃圾注册
  1756. add_action('register_post', 'codecheese_register_post', 10, 3);
  1757. function codecheese_register_post($sanitized_user_login, $user_email, $errors)
  1758. {
  1759. // Blocked domains
  1760. $domains = array(
  1761. 'net.buzzcluby.com',
  1762. 'buzzcluby.com',
  1763. 'mail.ru',
  1764. 'h.captchaeu.info',
  1765. 'edge.codyting.com'
  1766. );
  1767. // Get visitor email domain
  1768. $email = explode('@', $user_email);
  1769. // Check and display error message for the registration form if exists
  1770. if (in_array($email[1], $domains)) {
  1771. $errors->add('invalid_email', __('<b>ERROR</b>: This email domain (<b>@' . $email[1] . '</b>) has been blocked. Please use another email.'));
  1772. }
  1773. }
  1774. function array_html_props(array $props)
  1775. {
  1776. $props_string = '';
  1777. foreach ($props as $key => $value) {
  1778. $props_string .= ' ' . $key . '="' . $value . '"';
  1779. }
  1780. return $props_string;
  1781. }
  1782. /**
  1783. * 渲染一个懒加载的<img>
  1784. * @author KotoriK
  1785. */
  1786. function lazyload_img(string $src, string $class = '', array $otherParam = array())
  1787. {
  1788. $noscriptParam = $otherParam;
  1789. if ($class)
  1790. $noscriptParam['class'] = $class;
  1791. $noscriptParam['src'] = $src;
  1792. $otherParam['class'] = 'lazyload' . ($class ? ' ' . $class : '');
  1793. $otherParam['data-src'] = $src;
  1794. $otherParam['onerror'] = 'imgError(this)';
  1795. $otherParam['src'] = iro_opt('page_lazyload_spinner');
  1796. $noscriptProps = '';
  1797. $props = array_html_props($otherParam);
  1798. $noscriptProps = array_html_props($noscriptParam);
  1799. return "<img$props/><noscript><img$noscriptProps/></noscript>";
  1800. }
  1801. // html 标签处理器
  1802. function html_tag_parser($content)
  1803. {
  1804. if (!is_feed()) {
  1805. //图片懒加载标签替换
  1806. if (iro_opt('page_lazyload') && iro_opt('page_lazyload_spinner')) {
  1807. $img_elements = array();
  1808. $is_matched = preg_match_all('/<img[^<]*>/i', $content, $img_elements);
  1809. if ($is_matched) {
  1810. array_walk($img_elements[0], function ($img) use (&$content) {
  1811. $class_found = 0;
  1812. $new_img = preg_replace('/class=[\'"]([^\'"]+)[\'"]/i', 'class="$1 lazyload"', $img, -1, $class_found);
  1813. if ($class_found == 0) {
  1814. $new_img = str_replace('<img ', '<img class="lazyload"', $new_img);
  1815. }
  1816. $new_img = preg_replace('/srcset=[\'"]([^\'"]+)[\'"]/i', 'data-srcset="$1"', $new_img);
  1817. $new_img = preg_replace('/src=[\'"]([^\'"]+)[\'"]/i', 'data-src="$1" src="' . iro_opt('page_lazyload_spinner') . '" onerror="imgError(this)"', $new_img);
  1818. $content = str_replace($img, $new_img . '<noscript>' . $img . '</noscript>', $content);
  1819. });
  1820. }
  1821. }
  1822. //Fancybox
  1823. /* Markdown Regex Pattern for Matching URLs:
  1824. * https://daringfireball.net/2010/07/improved_regex_for_matching_urls
  1825. */
  1826. $url_regex = '((?:https?:\/\/|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:\'".,<>?«»“”‘’]))';
  1827. //With Thumbnail: !{alt}(url)[th_url]
  1828. if (preg_match_all('/\!\{.*?\)\[.*?\]/i', $content, $matches)) {
  1829. foreach ($matches as $result) {
  1830. $content = str_replace(
  1831. $result,
  1832. preg_replace(
  1833. '/!\{([^\{\}]+)*\}\(' . $url_regex . '\)\[' . $url_regex . '\]/i',
  1834. '<a data-fancybox="gallery"
  1835. data-caption="$1"
  1836. class="fancybox"
  1837. href="$2"
  1838. alt="$1"
  1839. title="$1"><img src="$7" target="_blank" rel="nofollow" class="fancybox"></a>',
  1840. $result
  1841. ),
  1842. $content
  1843. );
  1844. }
  1845. }
  1846. //Without Thumbnail :!{alt}(url)
  1847. $content = preg_replace(
  1848. '/!\{([^\{\}]+)*\}\(' . $url_regex . '\)/i',
  1849. '<a data-fancybox="gallery"
  1850. data-caption="$1"
  1851. class="fancybox"
  1852. href="$2"
  1853. alt="$1"
  1854. title="$1"><img src="$2" target="_blank" rel="nofollow" class="fancybox"></a>',
  1855. $content
  1856. );
  1857. }
  1858. //html tag parser for rss
  1859. if (is_feed()) {
  1860. //Fancybox
  1861. $url_regex = '((?:https?:\/\/|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:\'".,<>?«»“”‘’]))';
  1862. if (preg_match_all('/\!\{.*?\)\[.*?\]/i', $content, $matches)) {
  1863. foreach ($matches as $result) {
  1864. $content = str_replace(
  1865. $result,
  1866. preg_replace('/!\{([^\{\}]+)*\}\(' . $url_regex . '\)\[' . $url_regex . '\]/i', '<a href="$2"><img src="$7" alt="$1" title="$1"></a>', $result),
  1867. $content
  1868. );
  1869. }
  1870. }
  1871. $content = preg_replace('/!\{([^\{\}]+)*\}\(' . $url_regex . '\)/i', '<a href="$2"><img src="$2" alt="$1" title="$1"></a>', $content);
  1872. }
  1873. return $content;
  1874. }
  1875. add_filter('the_content', 'html_tag_parser'); //替换文章关键词
  1876. //add_filter( 'comment_text', 'html_tag_parser' );//替换评论关键词
  1877. /*
  1878. * QQ 评论
  1879. */
  1880. // 数据库插入评论表单的qq字段
  1881. add_action('wp_insert_comment', 'sql_insert_qq_field', 10, 2);
  1882. function sql_insert_qq_field($comment_ID, $commmentdata)
  1883. {
  1884. $qq = isset($_POST['new_field_qq']) ? $_POST['new_field_qq'] : false;
  1885. update_comment_meta($comment_ID, 'new_field_qq', $qq); // new_field_qq 是表单name值,也是存储在数据库里的字段名字
  1886. }
  1887. // 后台评论中显示qq字段
  1888. add_filter('manage_edit-comments_columns', 'add_comments_columns');
  1889. add_action('manage_comments_custom_column', 'output_comments_qq_columns', 10, 2);
  1890. function add_comments_columns($columns)
  1891. {
  1892. $columns['new_field_qq'] = __('QQ'); // 新增列名称
  1893. return $columns;
  1894. }
  1895. function output_comments_qq_columns($column_name, $comment_id)
  1896. {
  1897. switch ($column_name) {
  1898. case "new_field_qq":
  1899. // 这是输出值,可以拿来在前端输出,这里已经在钩子manage_comments_custom_column上输出了
  1900. echo get_comment_meta($comment_id, 'new_field_qq', true);
  1901. break;
  1902. }
  1903. }
  1904. /**
  1905. * 头像调用路径
  1906. */
  1907. add_filter('get_avatar', 'change_avatar', 10, 3);
  1908. function change_avatar($avatar)
  1909. {
  1910. global $comment, $sakura_privkey;
  1911. if ($comment && get_comment_meta($comment->comment_ID, 'new_field_qq', true)) {
  1912. $qq_number = get_comment_meta($comment->comment_ID, 'new_field_qq', true);
  1913. if (iro_opt('qq_avatar_link') == 'off') {
  1914. return '<img src="https://q2.qlogo.cn/headimg_dl?dst_uin=' . $qq_number . '&spec=100" class="lazyload avatar avatar-24 photo" alt="😀" width="24" height="24" onerror="imgError(this,1)">';
  1915. }
  1916. if (iro_opt('qq_avatar_link') == 'type_3') {
  1917. $qqavatar = file_get_contents('http://ptlogin2.qq.com/getface?appid=1006102&imgtype=3&uin=' . $qq_number);
  1918. preg_match('/:\"([^\"]*)\"/i', $qqavatar, $matches);
  1919. return '<img src="' . $matches[1] . '" class="lazyload avatar avatar-24 photo" alt="😀" width="24" height="24" onerror="imgError(this,1)">';
  1920. }
  1921. // Ensure $sakura_privkey is defined and not null
  1922. if (isset($sakura_privkey) && !is_null($sakura_privkey)) {
  1923. // 生成一个合适长度的初始化向量
  1924. $iv_length = openssl_cipher_iv_length('aes-128-cbc');
  1925. $iv = openssl_random_pseudo_bytes($iv_length);
  1926. // 加密数据
  1927. $encrypted = openssl_encrypt($qq_number, 'aes-128-cbc', $sakura_privkey, 0, $iv);
  1928. // 将初始化向量和加密数据一起编码
  1929. $encrypted = urlencode(base64_encode($iv . $encrypted));
  1930. return '<img src="' . rest_url("sakura/v1/qqinfo/avatar") . '?qq=' . $encrypted . '" class="lazyload avatar avatar-24 photo" alt="😀" width="24" height="24" onerror="imgError(this,1)">';
  1931. } else {
  1932. // Handle the case where $sakura_privkey is not set or is null
  1933. return '<img src="default_avatar_url" class="lazyload avatar avatar-24 photo" alt="😀" width="24" height="24" onerror="imgError(this,1)">';
  1934. }
  1935. }
  1936. return $avatar;
  1937. }
  1938. function get_random_url(string $url): string
  1939. {
  1940. $array = parse_url($url);
  1941. if (!isset($array['query'])) {
  1942. // 无参数
  1943. $url .= '?';
  1944. } else {
  1945. // 有参数
  1946. $url .= '&';
  1947. }
  1948. return $url . random_int(1, 100);
  1949. }
  1950. // default feature image
  1951. function DEFAULT_FEATURE_IMAGE(string $size = 'source'): string
  1952. {
  1953. if (iro_opt('post_cover_options') == 'type_2') {
  1954. return get_random_url(iro_opt('post_cover'));
  1955. }
  1956. if (iro_opt('random_graphs_options') == 'external_api') {
  1957. return get_random_url(iro_opt('random_graphs_link'));
  1958. }
  1959. $_api_url = rest_url('sakura/v1/image/feature');
  1960. $rand = rand(1, 100);
  1961. # 拼接符
  1962. $splice = strpos($_api_url, 'index.php?') !== false ? '&' : '?';
  1963. $_api_url = "{$_api_url}{$splice}size={$size}&$rand";
  1964. return $_api_url;
  1965. }
  1966. //评论回复
  1967. function sakura_comment_notify($comment_id)
  1968. {
  1969. if (!isset($_POST['mail-notify'])) {
  1970. update_comment_meta($comment_id, 'mail_notify', 'false');
  1971. }
  1972. }
  1973. add_action('comment_post', 'sakura_comment_notify');
  1974. //侧栏小工具
  1975. if (iro_opt('sakura_widget')) {
  1976. if (function_exists('register_sidebar')) {
  1977. register_sidebar(
  1978. array(
  1979. 'name' => __('Sidebar'), //侧栏
  1980. 'id' => 'sakura_widget',
  1981. 'before_widget' => '<div class="widget %2$s">',
  1982. 'after_widget' => '</div>',
  1983. 'before_title' => '<div class="title"><h2>',
  1984. 'after_title' => '</h2></div>',
  1985. )
  1986. );
  1987. }
  1988. }
  1989. // 评论Markdown解析
  1990. function markdown_parser($incoming_comment)
  1991. {
  1992. global $wpdb, $comment_markdown_content;
  1993. $re = '/```([\s\S]*?)```[\s]*|`{1,2}[^`](.*?)`{1,2}|\[.*?\]\([\s\S]*?\)/m';
  1994. if (preg_replace($re, 'temp', $incoming_comment['comment_content']) != strip_tags(preg_replace($re, 'temp', $incoming_comment['comment_content']))) {
  1995. siren_ajax_comment_err('评论只支持Markdown啦,见谅╮( ̄▽ ̄)╭<br>Markdown Supported while <i class="fa-solid fa-code"></i> Forbidden');
  1996. return ($incoming_comment);
  1997. }
  1998. $column_names = $wpdb->get_row("SELECT * FROM information_schema.columns where
  1999. table_name='$wpdb->comments' and column_name = 'comment_markdown' LIMIT 1");
  2000. //Add column if not present.
  2001. if (!isset($column_names)) {
  2002. $wpdb->query("ALTER TABLE $wpdb->comments ADD comment_markdown text");
  2003. }
  2004. $comment_markdown_content = $incoming_comment['comment_content'];
  2005. include 'inc/Parsedown.php';
  2006. $Parsedown = new Parsedown();
  2007. $incoming_comment['comment_content'] = $Parsedown->setUrlsLinked(false)->text($incoming_comment['comment_content']);
  2008. return $incoming_comment;
  2009. }
  2010. add_filter('preprocess_comment', 'markdown_parser');
  2011. remove_filter('comment_text', 'make_clickable', 9);
  2012. //保存Markdown评论
  2013. function save_markdown_comment($comment_ID, $comment_approved)
  2014. {
  2015. global $wpdb, $comment_markdown_content;
  2016. $comment = get_comment($comment_ID);
  2017. $comment_content = $comment_markdown_content;
  2018. //store markdow content
  2019. $wpdb->query("UPDATE $wpdb->comments SET comment_markdown='" . $comment_content . "' WHERE comment_ID='" . $comment_ID . "';");
  2020. }
  2021. add_action('comment_post', 'save_markdown_comment', 10, 2);
  2022. //打开评论HTML标签限制
  2023. function allow_more_tag_in_comment()
  2024. {
  2025. global $allowedtags;
  2026. $allowedtags['pre'] = array('class' => array());
  2027. $allowedtags['code'] = array('class' => array());
  2028. $allowedtags['h1'] = array('class' => array());
  2029. $allowedtags['h2'] = array('class' => array());
  2030. $allowedtags['h3'] = array('class' => array());
  2031. $allowedtags['h4'] = array('class' => array());
  2032. $allowedtags['h5'] = array('class' => array());
  2033. $allowedtags['ul'] = array('class' => array());
  2034. $allowedtags['ol'] = array('class' => array());
  2035. $allowedtags['li'] = array('class' => array());
  2036. $allowedtags['td'] = array('class' => array());
  2037. $allowedtags['th'] = array('class' => array());
  2038. $allowedtags['tr'] = array('class' => array());
  2039. $allowedtags['table'] = array('class' => array());
  2040. $allowedtags['thead'] = array('class' => array());
  2041. $allowedtags['tbody'] = array('class' => array());
  2042. $allowedtags['span'] = array('class' => array());
  2043. }
  2044. add_action('pre_comment_on_post', 'allow_more_tag_in_comment');
  2045. /**
  2046. * 检查数据库是否支持MyISAM引擎
  2047. */
  2048. function check_myisam_support()
  2049. {
  2050. global $wpdb;
  2051. $results = $wpdb->get_results("SHOW ENGINES");
  2052. if (!$results)
  2053. return false;
  2054. foreach ($results as $result) {
  2055. if ($result->Engine == "MyISAM") {
  2056. return $result->Support == "YES";
  2057. }
  2058. }
  2059. return false;
  2060. }
  2061. //rest api支持
  2062. function permalink_tip()
  2063. {
  2064. if (!get_option('permalink_structure')) {
  2065. $msg = __('<b> For a better experience, please do not set <a href="/wp-admin/options-permalink.php"> permalink </a> as plain. To do this, you may need to configure <a href="https://www.wpdaxue.com/wordpress-rewriterule.html" target="_blank"> pseudo-static </a>. </ b>', 'sakurairo'); /*<b>为了更好的使用体验,请不要将<a href="/wp-admin/options-permalink.php">固定链接</a>设置为朴素。为此,您可能需要配置<a href="https://www.wpdaxue.com/wordpress-rewriterule.html" target="_blank">伪静态</a>。</b>*/
  2066. echo '<div class="notice notice-success is-dismissible" id="scheme-tip"><p><b>' . $msg . '</b></p></div>';
  2067. }
  2068. }
  2069. add_action('admin_notices', 'permalink_tip');
  2070. //code end
  2071. //发送主题版本号
  2072. function send_theme_version()
  2073. {
  2074. $theme = wp_get_theme();
  2075. $version = $theme->get('Version');
  2076. $data = array(
  2077. 'date' => date('Y-m-d H:i:s'),
  2078. 'version' => $version
  2079. );
  2080. $args = array(
  2081. 'body' => $data,
  2082. 'timeout' => '5',
  2083. 'redirection' => '5',
  2084. 'httpversion' => '1.0',
  2085. 'blocking' => true,
  2086. 'headers' => array(),
  2087. 'cookies' => array()
  2088. );
  2089. wp_remote_post('https://api.maho.cc/ver-stat/index.php', $args);
  2090. }
  2091. if (iro_opt('send_theme_version') == '1') {
  2092. if (!wp_next_scheduled('daily_event')) {
  2093. wp_schedule_event(time(), 'daily', 'daily_event');
  2094. }
  2095. add_action('daily_event', 'send_theme_version');
  2096. }
  2097. //解析短代码
  2098. function register_shortcodes() {
  2099. add_shortcode('task', function($attr, $content = '') {
  2100. return '<div class="task shortcodestyle"><i class="fa-solid fa-clipboard-list"></i>' . $content . '</div>';
  2101. });
  2102. add_shortcode('warning', function($attr, $content = '') {
  2103. return '<div class="warning shortcodestyle"><i class="fa-solid fa-triangle-exclamation"></i>' . $content . '</div>';
  2104. });
  2105. add_shortcode('noway', function($attr, $content = '') {
  2106. return '<div class="noway shortcodestyle"><i class="fa-solid fa-square-xmark"></i>' . $content . '</div>';
  2107. });
  2108. add_shortcode('buy', function($attr, $content = '') {
  2109. return '<div class="buy shortcodestyle"><i class="fa-solid fa-square-check"></i>' . $content . '</div>';
  2110. });
  2111. add_shortcode('ghcard', function($attr, $content = '') {
  2112. $atts = shortcode_atts(array("path" => ""), $attr);
  2113. return '<div class="ghcard"><a href="https://github.com/' . esc_attr($atts['path']) . '"><img src="https://github-readme-stats.vercel.app/api' . esc_html($content) . '" alt="Github-Card"></a></div>';
  2114. });
  2115. add_shortcode('showcard', function($attr, $content = '') {
  2116. $atts = shortcode_atts(array("icon" => "", "title" => "", "img" => "", "color" => ""), $attr);
  2117. return sprintf(
  2118. '<div class="showcard">
  2119. <div class="img" alt="Show-Card" style="background:url(%s);background-size:cover;background-position: center;">
  2120. <a href="%s"><button class="showcard-button" style="color:%s !important;"><i class="fa-solid fa-angle-right"></i></button></a>
  2121. </div>
  2122. <div class="icon-title">
  2123. <i class="%s" style="color:%s !important;"></i>
  2124. <span class="title">%s</span>
  2125. </div>
  2126. </div>',
  2127. $atts['img'],
  2128. $content,
  2129. esc_attr($atts['color']),
  2130. esc_attr($atts['icon']),
  2131. esc_attr($atts['color']),
  2132. $atts['title'],
  2133. );
  2134. });
  2135. add_shortcode('conversations', function($attr, $content = '') {
  2136. $atts = shortcode_atts(array("avatar" => "", "direction" => "", "username" => ""), $attr);
  2137. if (empty($atts['avatar']) && !empty($atts['username'])) {
  2138. $user = get_user_by('login', $atts['username']);
  2139. if ($user) {
  2140. $atts['avatar'] = get_avatar_url($user->ID, 40);
  2141. }
  2142. }
  2143. $speaker_alt = $atts['username'] ? '<span class="screen-reader-text">' . sprintf(__("%s says: ", "sakurairo"), esc_html($atts['username'])) . '</span>' : "";
  2144. return sprintf(
  2145. '<div class="conversations-code" style="flex-direction: %s;">
  2146. <img src="%s">
  2147. <div class="conversations-code-text">%s%s</div>
  2148. </div>',
  2149. esc_attr($atts['direction']),
  2150. $atts['avatar'],
  2151. $speaker_alt,
  2152. $content
  2153. );
  2154. });
  2155. add_shortcode('collapse', function($atts, $content = null) {
  2156. $atts = shortcode_atts(array("title" => ""), $atts);
  2157. ob_start();
  2158. ?>
  2159. <a href="javascript:void(0)" class="collapseButton">
  2160. <div class="collapse shortcodestyle">
  2161. <i class="fa-solid fa-angle-down"></i>
  2162. <span class="title"><?= $atts['title'] ?></span>
  2163. <span class="ecbutton"><?php _e('Expand / Collapse', 'sakurairo'); ?></span>
  2164. </div>
  2165. </a>
  2166. <div class="xContent" style="display: none;"><?= do_shortcode($content) ?></div>
  2167. <?php
  2168. return ob_get_clean();
  2169. });
  2170. }
  2171. add_action('init', 'register_shortcodes');
  2172. //code end
  2173. //WEBP支持
  2174. function mimvp_filter_mime_types($array)
  2175. {
  2176. $array['webp'] = 'image/webp';
  2177. return $array;
  2178. }
  2179. add_filter('mime_types', 'mimvp_filter_mime_types', 10, 1);
  2180. function mimvp_file_is_displayable_image($result, $path)
  2181. {
  2182. $info = @getimagesize($path);
  2183. // if ($info['mime'] == 'image/webp') {
  2184. // $result = true;
  2185. // }
  2186. // return $result;
  2187. return (bool) ($info); // 根据文档这里需要返回一个bool
  2188. }
  2189. add_filter('file_is_displayable_image', 'mimvp_file_is_displayable_image', 10, 2);
  2190. //code end
  2191. if (!iro_opt('login_language_opt') == '1') {
  2192. add_filter('login_display_language_dropdown', '__return_false');
  2193. }
  2194. if (iro_opt('captcha_select') === 'iro_captcha') {
  2195. function login_CAPTCHA()
  2196. {
  2197. include_once('inc/classes/Captcha.php');
  2198. $img = new Sakura\API\Captcha;
  2199. $test = $img->create_captcha_img();
  2200. echo '<p><label for="captcha" class="captcha">验证码<br><img id="captchaimg" width="120" height="40" src="', $test['data'], '"><input type="text" name="yzm" id="yzm" class="input" value="" size="20" tabindex="4" placeholder="请输入验证码"><input type="hidden" name="timestamp" value="', $test['time'], '"><input type="hidden" name="id" value="', $test['id'], '">'
  2201. . "</label></p>";
  2202. }
  2203. add_action('login_form', 'login_CAPTCHA');
  2204. add_action('register_form', 'login_CAPTCHA');
  2205. add_action('lostpassword_form', 'login_CAPTCHA');
  2206. /**
  2207. * 登录界面验证码验证
  2208. */
  2209. function CAPTCHA_CHECK($user, $username, $password)
  2210. {
  2211. if (empty($_POST)) {
  2212. return new WP_Error();
  2213. }
  2214. if (!(isset($_POST['yzm']) && !empty(trim($_POST['yzm'])))) {
  2215. return new WP_Error('prooffail', '<strong>错误</strong>:验证码为空!');
  2216. }
  2217. if (!isset($_POST['timestamp']) || !isset($_POST['id']) || !preg_match('/^[\w$.\/]+$/', $_POST['id']) || !ctype_digit($_POST['timestamp'])) {
  2218. return new WP_Error('prooffail', '<strong>错误</strong>:非法数据');
  2219. }
  2220. include_once('inc/classes/Captcha.php');
  2221. $img = new Sakura\API\Captcha;
  2222. $check = $img->check_captcha($_POST['yzm'], $_POST['timestamp'], $_POST['id']);
  2223. if ($check['code'] == 5) {
  2224. return $user;
  2225. }
  2226. return new WP_Error('prooffail', '<strong>错误</strong>:' . $check['msg']);
  2227. //return home_url('/wp-admin/');
  2228. }
  2229. add_filter('authenticate', 'CAPTCHA_CHECK', 20, 3);
  2230. /**
  2231. * 忘记密码界面验证码验证
  2232. */
  2233. function lostpassword_CHECK($errors)
  2234. {
  2235. if (empty($_POST)) {
  2236. return false;
  2237. }
  2238. if (isset($_POST['yzm']) && !empty(trim($_POST['yzm']))) {
  2239. if (!isset($_POST['timestamp']) || !isset($_POST['id']) || !preg_match('/^[\w$.\/]+$/', $_POST['id']) || !ctype_digit($_POST['timestamp'])) {
  2240. return new WP_Error('prooffail', '<strong>错误</strong>:非法数据');
  2241. }
  2242. include_once('inc/classes/Captcha.php');
  2243. $img = new Sakura\API\Captcha;
  2244. $check = $img->check_captcha($_POST['yzm'], $_POST['timestamp'], $_POST['id']);
  2245. if ($check['code'] != 5) {
  2246. return $errors->add('invalid_department ', '<strong>错误</strong>:' . $check['msg']);
  2247. }
  2248. } else {
  2249. return $errors->add('invalid_department', '<strong>错误</strong>:验证码为空!');
  2250. }
  2251. }
  2252. add_action('lostpassword_post', 'lostpassword_CHECK');
  2253. /**
  2254. * 注册界面验证码验证
  2255. */
  2256. function registration_CAPTCHA_CHECK($errors, $sanitized_user_login, $user_email)
  2257. {
  2258. if (empty($_POST)) {
  2259. return new WP_Error();
  2260. }
  2261. if (!(isset($_POST['yzm']) && !empty(trim($_POST['yzm'])))) {
  2262. return new WP_Error('prooffail', '<strong>错误</strong>:验证码为空!');
  2263. }
  2264. if (!isset($_POST['timestamp']) || !isset($_POST['id']) || !preg_match('/^[\w$.\/]+$/', $_POST['id']) || !ctype_digit($_POST['timestamp'])) {
  2265. return new WP_Error('prooffail', '<strong>错误</strong>:非法数据');
  2266. }
  2267. include_once('inc/classes/Captcha.php');
  2268. $img = new Sakura\API\Captcha;
  2269. $check = $img->check_captcha($_POST['yzm'], $_POST['timestamp'], $_POST['id']);
  2270. if ($check['code'] == 5)
  2271. return $errors;
  2272. return new WP_Error('prooffail', '<strong>错误</strong>:' . $check['msg']);
  2273. }
  2274. add_filter('registration_errors', 'registration_CAPTCHA_CHECK', 2, 3);
  2275. } elseif ((iro_opt('captcha_select') === 'vaptcha') && (!empty(iro_opt("vaptcha_vid")) && !empty(iro_opt("vaptcha_key")))) {
  2276. function vaptchaInit()
  2277. {
  2278. include_once('inc/classes/Vaptcha.php');
  2279. $vaptcha = new Sakura\API\Vaptcha;
  2280. echo $vaptcha->html();
  2281. echo $vaptcha->script();
  2282. }
  2283. add_action('login_form', 'vaptchaInit');
  2284. function checkVaptchaAction($user)
  2285. {
  2286. if (empty($_POST)) {
  2287. return new WP_Error();
  2288. }
  2289. if (!(isset($_POST['vaptcha_server']) && isset($_POST['vaptcha_token']))) {
  2290. return new WP_Error('prooffail', '<strong>错误</strong>:请先进行人机验证');
  2291. }
  2292. if (!preg_match('/^https:\/\/([\w-]+\.)+[\w-]*([^<>=?\"\'])*$/', $_POST['vaptcha_server']) || !preg_match('/^[\w\-\$]+$/', $_POST['vaptcha_token'])) {
  2293. return new WP_Error('prooffail', '<strong>错误</strong>:非法数据');
  2294. }
  2295. include_once('inc/classes/Vaptcha.php');
  2296. $url = $_POST['vaptcha_server'];
  2297. $token = $_POST['vaptcha_token'];
  2298. $ip = get_the_user_ip();
  2299. $vaptcha = new Sakura\API\Vaptcha;
  2300. $response = $vaptcha->checkVaptcha($url, $token, $ip);
  2301. if ($response->msg && $response->success && $response->score) {
  2302. if ($response->success === 1 && $response->score >= 70) {
  2303. return $user;
  2304. }
  2305. if ($response->success === 0) {
  2306. $errorcode = $response->msg;
  2307. return new WP_Error('prooffail', '<strong>错误</strong>:' . $errorcode);
  2308. }
  2309. return new WP_Error('prooffail', '<strong>错误</strong>:人机验证失败');
  2310. } else if (is_string($response)) {
  2311. return new WP_Error('prooffail', '<strong>错误</strong>:' . $response);
  2312. }
  2313. return new WP_Error('prooffail', '<strong>错误</strong>:未知错误');
  2314. }
  2315. add_filter('authenticate', 'checkVaptchaAction', 20, 3);
  2316. }
  2317. /**
  2318. * 返回是否应当显示文章标题。
  2319. *
  2320. */
  2321. function should_show_title(): bool
  2322. {
  2323. $id = get_the_ID();
  2324. $use_as_thumb = get_post_meta($id, 'use_as_thumb', true); //'true','only',(default)
  2325. return !iro_opt('patternimg')
  2326. || !get_post_thumbnail_id($id)
  2327. && $use_as_thumb != 'true' && !get_post_meta($id, 'video_cover', true);
  2328. }
  2329. /**
  2330. * 修复 WordPress 搜索结果为空,返回为 200 的问题。
  2331. * @author ivampiresp <im@ivampiresp.com>
  2332. */
  2333. function search_404_fix_template_redirect()
  2334. {
  2335. if (is_search()) {
  2336. global $wp_query;
  2337. if ($wp_query->found_posts == 0) {
  2338. status_header(404);
  2339. }
  2340. }
  2341. }
  2342. add_action('template_redirect', 'search_404_fix_template_redirect');
  2343. // 给上传图片增加时间戳
  2344. add_filter('wp_handle_upload_prefilter', function ($file) {
  2345. $file['name'] = time() . '-' . $file['name'];
  2346. return $file;
  2347. });
  2348. /**
  2349. * 在后台评论列表中添加IP地理位置信息列
  2350. *
  2351. * @param string[] $columns 列表标题的标签
  2352. * @return void
  2353. */
  2354. function iro_add_location_to_comments_columns($columns)
  2355. {
  2356. $columns['iro_ip_location'] = __('Location', 'sakurairo');
  2357. return $columns;
  2358. }
  2359. /**
  2360. * 将IP地理位置信息输出到评论列表中
  2361. *
  2362. * @param string $column_name 列表标题的标签
  2363. * @param int $comment_id 评论ID
  2364. * @return void
  2365. */
  2366. function iro_output_ip_location_columns($column_name, $comment_id)
  2367. {
  2368. switch ($column_name) {
  2369. case "iro_ip_location":
  2370. echo \Sakura\API\IpLocationParse::getIpLocationByCommentId($comment_id);
  2371. break;
  2372. }
  2373. }
  2374. if (iro_opt('show_location_in_manage')) {
  2375. add_filter('manage_edit-comments_columns', 'iro_add_location_to_comments_columns');
  2376. add_action('manage_comments_custom_column', 'iro_output_ip_location_columns', 10, 2);
  2377. }
  2378. // Modify search query to exclude pages and categories(修改搜索查询以排除'页面'和'类别')
  2379. function exclude_pages_and_categories_from_search($query) {
  2380. if (!is_admin() && $query->is_search) {
  2381. // Exclude pages
  2382. $query->set('post_type', array('post', 'shuoshuo', 'link')); // Include other post types but exclude 'page'
  2383. // Exclude categories
  2384. $tax_query = array(
  2385. array(
  2386. 'taxonomy' => 'category',
  2387. 'field' => 'name',
  2388. 'terms' => get_search_query(),
  2389. 'operator' => 'NOT IN'
  2390. )
  2391. );
  2392. $query->set('tax_query', $tax_query);
  2393. }
  2394. return $query;
  2395. }
  2396. add_filter('pre_get_posts', 'exclude_pages_and_categories_from_search');
  2397. function iterator_to_string(Iterator $iterator): string
  2398. {
  2399. $content = '';
  2400. foreach ($iterator as $item) {
  2401. $content .= $item;
  2402. }
  2403. return $content;
  2404. }