您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

1164 行
40 KiB

  1. <?php
  2. /**
  3. * Plugin name: sandbox adaptions
  4. * Plugin URI: https://www.netzgestaltung.at
  5. * Author: Thomas Fellinger
  6. * Author URI: https://www.netzgestaltung.at
  7. * Version: 0.1
  8. * Description: Custom website functions
  9. * License: GPL v2
  10. * Copyright 2020 Thomas Fellinger (email : office@netzgestaltung.at)
  11. * This program is free software: you can redistribute it and/or modify
  12. * it under the terms of the GNU General Public License as published by
  13. * the Free Software Foundation, either version 2 of the License, or
  14. * (at your option) any later version.
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  22. */
  23. define('SANDBOX_ADAPTIONS_PATH', plugin_dir_path(__FILE__));
  24. define('SANDBOX_ADAPTIONS_URL', plugin_dir_url(__FILE__));
  25. /**
  26. * Ajax hooks
  27. * ==========
  28. */
  29. // user edit ajax
  30. add_action('wp_ajax_user_edit', 'sandbox_ajax_user_edit');
  31. /**
  32. * Plugin setup hook
  33. * ================
  34. */
  35. add_action('plugins_loaded', 'sandbox_setup_site');
  36. function sandbox_setup_site() {
  37. add_post_type_support('page', 'excerpt');
  38. // init image sizes
  39. sandbox_image_sizes();
  40. // init custom widgets
  41. add_action('widgets_init', 'sandbox_widgets_init');
  42. // disable emoji support for more pagespeed
  43. add_action('init', 'sandbox_disable_emojis');
  44. // remove unused default taxonomies
  45. add_action('init', 'sandbox_unregister_taxonomies');
  46. // load admin styles
  47. add_action('admin_head', 'sandbox_admin_styles_load');
  48. // remove WLW
  49. // https://wphacks.wordpress.com/2008/08/27/wordpress-tip-remove-wlw-rsd-link/
  50. remove_action('wp_head', 'wlwmanifest_link');
  51. // remove xml-rpc edit link
  52. remove_action('wp_head', 'rsd_link');
  53. // Remove generator info
  54. // https://bhoover.com/remove-unnecessary-code-from-your-wordpress-blog-header/
  55. remove_action('wp_head', 'wp_generator');
  56. // remove wp-sitemap.xml when using a xml sitemap plugin
  57. add_filter('wp_sitemaps_enabled', '__return_false');
  58. // quick fix for https://wordpress.org/support/topic/jqeuery-error-live-is-not-a-function/
  59. add_action('admin_enqueue_scripts', 'sandbox_jcf_admin_fix');
  60. // add a position field to user profile
  61. // add_action( 'show_user_profile', 'sandbox_user_profile' );
  62. // add_action( 'edit_user_profile', 'sandbox_user_profile' );
  63. // save/update position user profile field
  64. // add_action( 'personal_options_update', 'sandbox_save_user_profile' );
  65. // add_action( 'edit_user_profile_update', 'sandbox_save_user_profile' );
  66. if ( !is_admin() ) {
  67. // add usefull classNames
  68. add_filter('body_class', 'sandbox_body_class');
  69. add_filter('post_class', 'sandbox_post_class');
  70. add_filter('nav_menu_css_class', 'sandbox_menu_item_class', 10, 2);
  71. add_filter('the_category', 'sandbox_category_class');
  72. // adds login and out links to menus "site-loggedin" and "site-loggedout"
  73. add_filter('wp_nav_menu_items', 'sandbox_nav_menu_items', 10, 2);
  74. // Custom login screen
  75. add_filter('login_headerurl', 'sandbox_login_headerurl');
  76. add_filter('login_headertext', 'sandbox_login_headertext');
  77. add_filter('login_enqueue_scripts', 'sandbox_login_enqueue_scripts');
  78. // Change Wordpress email subject
  79. add_filter('wp_mail_from_name', 'sandbox_mail_from_name');
  80. // remove lazy block wrapper container markup in frontend
  81. add_filter( 'lzb/block_render/allow_wrapper', '__return_false' );
  82. // custom archive query settings
  83. add_action( 'pre_get_posts', 'sandbox_archive_query');
  84. // Admin pages related stuff
  85. } else {
  86. // add usefull classNames
  87. add_filter('admin_body_class', 'sandbox_admin_body_class');
  88. }
  89. // plugin integrations
  90. // lazy block Handlebars helper
  91. add_action('lzb_handlebars_object', 'sandbox_lazyblock_handlebars_helper');
  92. // listo order for cf7 select input
  93. add_filter('wpcf7_form_tag_data_option', 'sandbox_listo_ordered', 11, 1);
  94. // listo uses an iso3 country list
  95. // country iso2 to iso3:
  96. // https://github.com/i-rocky/country-list-js/blob/master/data/iso_alpha_3.json
  97. // all countries and phone-codes (iso2):
  98. // https://github.com/ChromaticHQ/intl-tel-input/blob/master/src/js/data.js
  99. // handle required attribute
  100. add_filter('wpcf7_form_elements', 'sandbox_wpcf7_form_elements');
  101. // filter values of form tags to email
  102. add_filter( 'cf7sg_mailtag_email-updates', 'sandbox_cf7_mailtag_email_updates', 10, 3);
  103. // remove layout from "cf7 smart grid plugin"
  104. // add_action('smart_grid_register_styles', 'sandbox_smart_grid_register_styles');
  105. // use really simple captcha in contact form 7
  106. // add_filter('wpcf7_use_really_simple_captcha', '__return_true');
  107. // CF7 gated content with custom field
  108. add_filter('do_shortcode_tag', 'sandbox_cf7_gated_content', 10, 3);
  109. }
  110. // Check if function "wp_body_open" exits, if not create it
  111. if ( !function_exists('wp_body_open') ) {
  112. function wp_body_open() {
  113. do_action('wp_body_open');
  114. }
  115. }
  116. // add custom image sizes
  117. function sandbox_image_sizes() {
  118. $image_sizes = sandbox_get_image_sizes();
  119. if ( !empty( $image_sizes ) ) {
  120. foreach ( $image_sizes as $id => $size ) {
  121. add_image_size( $id, $size['args']['w'], $size['args']['h'], $size['args']['crop'] );
  122. }
  123. }
  124. }
  125. /**
  126. * custom image sizes settings
  127. *
  128. * @see https://en.wikipedia.org/wiki/16:9_aspect_ratio
  129. */
  130. function sandbox_get_image_sizes() {
  131. $sizes = array();
  132. // larger thumbnail
  133. $sizes['thumbnail-semi-large'] = array(
  134. 'title' => __('Thumbnail-Semi-Large', 'sandbox'),
  135. 'args' => array(
  136. 'w' => 640,
  137. 'h' => 640,
  138. 'crop' => true,
  139. ),
  140. );
  141. // Standard (with sidebar) 16:9
  142. $sizes['sandbox-default'] = array(
  143. 'title' => __('Standard (with sidebar)', 'sandbox'),
  144. 'args' => array(
  145. 'w' => 800,
  146. 'h' => 450,
  147. 'crop' => true,
  148. ),
  149. );
  150. //Full width (no sidebar) 16:9
  151. $sizes['sandbox-wide'] = array(
  152. 'title' => __('Full Width (no sidebar)', 'sandbox'),
  153. 'args' => array(
  154. 'w' => 1280,
  155. 'h' => 720,
  156. 'crop' => true,
  157. ),
  158. );
  159. // Hero image 16:9
  160. $sizes['sandbox-hero'] = array(
  161. 'title' => __('Hero image', 'sandbox'),
  162. 'args' => array(
  163. 'w' => 1920,
  164. 'h' => 1080,
  165. 'crop' => true,
  166. ),
  167. );
  168. // Hero image 16:9
  169. $sizes['blog-hero'] = array(
  170. 'title' => __('Hero image', 'sandbox'),
  171. 'args' => array(
  172. 'w' => 1500,
  173. 'h' => 476,
  174. 'crop' => true,
  175. ),
  176. );
  177. // keep aspect ratio
  178. $sizes['semi-large'] = array(
  179. 'title' => __('Semi-Large', 'sandbox'),
  180. 'args' => array(
  181. 'w' => 640,
  182. 'h' => 640,
  183. 'crop' => false,
  184. ),
  185. );
  186. return $sizes;
  187. }
  188. // Custom login screen - home url
  189. function sandbox_login_headerurl(){
  190. return home_url();
  191. }
  192. // Custom login screen - header text
  193. function sandbox_login_headertext(){
  194. return wp_get_document_title();
  195. }
  196. // Custom login screen - login style
  197. function sandbox_login_enqueue_scripts(){
  198. // loads style/images from template folder
  199. wp_register_style('sandbox_login', get_template_directory_uri() . '/css/login.css');
  200. wp_enqueue_style('sandbox_login');
  201. }
  202. // init custom widgets
  203. function sandbox_widgets_init(){
  204. register_widget('sandbox_faq_nav_widget');
  205. // register_widget('sandbox_events_widget');
  206. // register_widget('sandbox_social_widget');
  207. // register_widget('sandbox_slider_widget');
  208. }
  209. /**
  210. * Disable the emoji's
  211. * https://kinsta.com/knowledgebase/disable-emojis-wordpress/
  212. */
  213. function sandbox_disable_emojis(){
  214. remove_action('wp_head', 'print_emoji_detection_script', 7 );
  215. remove_action('admin_print_scripts', 'print_emoji_detection_script');
  216. remove_action('wp_print_styles', 'print_emoji_styles');
  217. remove_action('admin_print_styles', 'print_emoji_styles');
  218. remove_filter('the_content_feed', 'wp_staticize_emoji');
  219. remove_filter('comment_text_rss', 'wp_staticize_emoji');
  220. remove_filter('wp_mail', 'wp_staticize_emoji_for_email');
  221. add_filter('tiny_mce_plugins', 'disable_emojis_tinymce');
  222. add_filter('wp_resource_hints', 'disable_emojis_remove_dns_prefetch', 10, 2 );
  223. }
  224. /**
  225. * Filter function used to remove the tinymce emoji plugin.
  226. *
  227. * @param array $plugins
  228. * @return array Difference betwen the two arrays
  229. */
  230. function disable_emojis_tinymce($plugins) {
  231. if ( is_array($plugins) ) {
  232. return array_diff($plugins, array('wpemoji'));
  233. } else {
  234. return array();
  235. }
  236. }
  237. /**
  238. * Remove emoji CDN hostname from DNS prefetching hints.
  239. *
  240. * @param array $urls URLs to print for resource hints.
  241. * @param string $relation_type The relation type the URLs are printed for.
  242. * @return array Difference betwen the two arrays.
  243. */
  244. function disable_emojis_remove_dns_prefetch( $urls, $relation_type ) {
  245. if ( 'dns-prefetch' == $relation_type ) {
  246. /** This filter is documented in wp-includes/formatting.php */
  247. $emoji_svg_url = apply_filters('emoji_svg_url', 'https://s.w.org/images/core/emoji/2/svg/');
  248. $urls = array_diff( $urls, array( $emoji_svg_url ) );
  249. }
  250. return $urls;
  251. }
  252. // remove unused default taxonomies
  253. function sandbox_unregister_taxonomies(){
  254. register_taxonomy('category', array(), array('show_in_nav_menus' => false));
  255. }
  256. // adds usefull body classNames
  257. // @param $classes array
  258. function sandbox_body_class($classes){
  259. $classNames = array();
  260. $post = get_post();
  261. $parents = get_post_ancestors($post);
  262. $slug = sandbox_get_the_slug();
  263. $post_type = get_post_type();
  264. $classNames[] = $post_type . '-' . $slug;
  265. if ( is_home() ) {
  266. $classNames[] = 'archive';
  267. }
  268. if ( is_active_sidebar('content-before') && is_active_sidebar('content-after') ) {
  269. $classNames[] = 'has-content-sidebars';
  270. } else if ( is_active_sidebar('content-before') || is_active_sidebar('content-after') ) {
  271. $classNames[] = 'has-content-sidebar';
  272. if ( is_active_sidebar('content-before') ) {
  273. $classNames[] = 'has-sidebar-content-before';
  274. } else if ( is_active_sidebar('content-after') ) {
  275. $classNames[] = 'has-sidebar-content-after';
  276. }
  277. }
  278. /* use for parent pages as sections
  279. if ( !empty($parents) ) {
  280. $parents[] = $post->ID;
  281. foreach ( $parents as $parentID ) {
  282. if ( $parentID === 8 ) {
  283. $classNames[] = 'section-you-name-it';
  284. }
  285. }
  286. }
  287. */
  288. // echo var_dump($classes);
  289. return array_merge( $classes, $classNames );
  290. }
  291. // add usefull classNames
  292. // @param $classes string
  293. function sandbox_admin_body_class($classes){
  294. $classNames = '';
  295. $screen = get_current_screen();
  296. if ( $screen->base === 'post' && $screen->post_type === 'page' ) {
  297. $page_template = get_post_meta(get_the_ID(), '_wp_page_template', true);
  298. $classNames .= ' used-template-' . esc_attr(str_replace('.php', '', $page_template));
  299. }
  300. return $classes . ' ' . $classNames;
  301. }
  302. // add custom styles for admin section
  303. function sandbox_admin_styles_load(){
  304. wp_register_style('sandbox_admin', SANDBOX_ADAPTIONS_URL . '/admin/style.css');
  305. wp_enqueue_style('sandbox_admin');
  306. }
  307. function sandbox_jcf_admin_fix(){
  308. $screen = get_current_screen();
  309. if ( in_array($screen->id, array('settings_page_jcf_admin', 'settings_page_jcf_fieldset_index')) ) {
  310. wp_enqueue_script('jquery-migrate');
  311. }
  312. }
  313. // add a position field to user profile
  314. function sandbox_user_profile($user) { ?>
  315. <h3>Extra profile information</h3>
  316. <table class="form-table">
  317. <tr>
  318. <th><label for="twitter">Position</label></th>
  319. <td>
  320. <input type="text" name="_position" id="position" value="<?php echo esc_attr(get_the_author_meta( '_position', $user->ID)); ?>" class="regular-text" /><br />
  321. <span class="description">Please enter position at your organisation.</span>
  322. </td>
  323. </tr>
  324. <tr>
  325. <th><label for="linkedin">LinkedIn</label></th>
  326. <td>
  327. <input type="text" name="_linkedin" id="linkedin" value="<?php echo esc_attr(get_the_author_meta( '_linkedin', $user->ID)); ?>" class="regular-text" /><br />
  328. <span class="description">Please enter your LinkedIn username.</span>
  329. </td>
  330. </tr>
  331. </table>
  332. <?php }
  333. // save/update position user profile field
  334. function sandbox_save_user_profile($user_id){
  335. if ( !current_user_can('edit_user', $user_id) )
  336. return false;
  337. // Copy and paste this line for additional fields. Make sure to change '_position' to the field ID.
  338. update_usermeta($user_id, '_position', $_POST['_position']);
  339. /* Copy and paste this line for additional fields. Make sure to change 'twitter' to the field ID. */
  340. update_usermeta($user_id, '_linkedin', $_POST['_linkedin']);
  341. }
  342. // adds usefull post classNames
  343. function sandbox_post_class($classes){
  344. $classNames = array();
  345. if ( !has_post_thumbnail() ) {
  346. $classNames[] = 'no-post-thumbnail';
  347. }
  348. return array_merge($classes, $classNames);
  349. }
  350. // adds usefull menu-item classNames
  351. function sandbox_menu_item_class($classes, $item){
  352. // Add slugs to menu-items
  353. if ('category' == $item->object ) {
  354. $category = get_category( $item->object_id );
  355. $classes[] = 'category-' . $category->slug;
  356. } else if ('format' == $item->object ){
  357. $format = get_term($item->object_id);
  358. $classes[] = 'format-' . $format->slug;
  359. }
  360. return $classes;
  361. }
  362. // adds usefull category classNames
  363. function sandbox_category_class($thelist){
  364. $categories = get_the_category();
  365. if ( !$categories || is_wp_error($categories) ) {
  366. return $thelist;
  367. }
  368. $output = '<ul class="post-categories">';
  369. foreach ( $categories as $category ) {
  370. $output .= '<li class="category-' . $category->slug . '"><a href="' . esc_url(get_category_link($category->term_id)) . '">' . $category->name . '</a></li>';
  371. }
  372. $output .= '</ul>';
  373. return $output;
  374. }
  375. // adds login and out links to menus "site-loggedin" and "site-loggedout"
  376. function sandbox_nav_menu_items($items, $args){
  377. if ( is_user_logged_in() ) {
  378. if ( $args->menu->slug === 'site-loggedin' ) {
  379. // add logout link to the end of the menu
  380. $logout_class = 'menu-item-logout menu-item menu-item-type-custom menu-item-object-custom';
  381. $items .= '<li class="' . $logout_class . '">' . wp_loginout(get_permalink(), false) . '</li>';
  382. }
  383. } elseif ( $args->menu->slug === 'site-loggedout' ) {
  384. // add login link to the begin of the menu
  385. $login_class = 'menu-item-login menu-item menu-item-type-custom menu-item-object-custom';
  386. $items = '<li class="' . $login_class . '">' . wp_loginout(get_permalink(), false) . '</li>' . $items;
  387. }
  388. return $items;
  389. }
  390. /**
  391. * user edit ajax system
  392. * =====================
  393. * passwords strenght meter taken from:
  394. * https://code.tutsplus.com/articles/using-the-included-password-strength-meter-script-in-wordpress--wp-34736
  395. * https://github.com/WordPress/WordPress/blob/master/wp-admin/js/user-profile.js#L223
  396. * ajax idea:
  397. * https://wordpress.stackexchange.com/questions/274778/updating-user-profile-with-ajax-not-working
  398. * form field validation:
  399. * https://itnext.io/https-medium-com-joshstudley-form-field-validation-with-html-and-a-little-javascript-1bda6a4a4c8c
  400. * page template idea:
  401. * https://wordpress.stackexchange.com/questions/9775/how-to-edit-a-user-profile-on-the-front-end
  402. */
  403. function sandbox_ajax_user_edit(){
  404. check_ajax_referer('sandbox_ajax_call', 'verify');
  405. // list of valid field names
  406. $fields = array('user_login', 'first_name', 'last_name', 'nickname', 'display_name', 'pass1');
  407. if ( isset($_POST['field_name']) ) {
  408. $field_name = $_POST['field_name'];
  409. if ( in_array($field_name, $fields) ) { // valid field
  410. if ( isset($_POST[$field_name]) ) { // field value is set
  411. $value = filter_var(trim($_POST[$_POST['field_name']]), FILTER_SANITIZE_STRING);
  412. $pattern = '/[A-Za-z0-9 ]{3,32}/';
  413. if ( $_POST['field_name'] === 'nickname' ) {
  414. $pattern = '/[a-zA-Z0-9-_ ]{3,32}/';
  415. }
  416. if ( $_POST['field_name'] === 'pass1' ) {
  417. $pattern = '/^[^\\\\]*$/';
  418. }
  419. if ( preg_match($pattern, $value) ) { // check valid pattern
  420. $current_user = wp_get_current_user();
  421. // reset $_POST
  422. $_POST = array(
  423. 'email' => $current_user->user_email,
  424. );
  425. if ( $field_name !== 'nickname' ) {
  426. $_POST['nickname'] = $current_user->nickname;
  427. }
  428. // readd value
  429. $_POST[$field_name] = $value;
  430. if ( $field_name === 'pass1' ) {
  431. $_POST['pass2'] = $value;
  432. }
  433. $edited_user = edit_user($current_user->ID);
  434. if ( gettype($edited_user) === "integer" ) {
  435. $json = array('error' => false, 'message' => 'Value "' . $value . '" for field "' . $field_name . '" was saved');
  436. } else {
  437. $json = array('error' => true, 'debug' => array('user_edit' => $edited_user), 'message' => 'User was not saved, look at "debug" array');
  438. }
  439. } else {
  440. $json = array('error' => true, 'message' => 'Value for field "' . $_POST['field_name'] . '" is not valid');
  441. }
  442. } else {
  443. $json = array('error' => true, 'message' => 'No value for field "' . $_POST['field_name'] . '" sent');
  444. }
  445. } else {
  446. $json = array('error' => true, 'message' => 'Given fieldname "' . $_POST['field_name'] . '" is not valid');
  447. }
  448. } else {
  449. $json = array('error' => true, 'message' => 'No "field" Param fieldname sent');
  450. }
  451. wp_send_json($json);
  452. }
  453. // Change Wordpress email subject
  454. function sandbox_mail_from_name($name){
  455. return get_bloginfo('name', 'display');
  456. }
  457. // custom archive query settings
  458. function sandbox_archive_query($query){
  459. if ( $query->is_main_query() && !is_admin() ) {
  460. if ( is_post_type_archive('aktivitaet') ) {
  461. //If you wanted it for the archive of a custom post type use: is_post_type_archive( $post_type )
  462. $query->set('meta_key', '_date-begin');
  463. //Set the orderby
  464. $query->set('orderby', 'meta_value');
  465. //Set the order ASC or DESC
  466. $query->set('order', 'ASC');
  467. }
  468. }
  469. }
  470. /**
  471. * lazy block Handlebars helper
  472. *
  473. * image sizes helper
  474. * https://github.com/nk-o/lazy-blocks/issues/68
  475. */
  476. function sandbox_lazyblock_handlebars_helper($handlebars){
  477. $handlebars->registerHelper('wp_get_attachment_image', function($image, $size=null){
  478. if ( isset($image['id']) ) {
  479. return wp_get_attachment_image($image['id'], $size);
  480. }
  481. });
  482. }
  483. /**
  484. * Sort countries list by name instead country-iso-code
  485. * https://wordpress.org/support/topic/excellent-9087/
  486. */
  487. function sandbox_listo_ordered($data){
  488. if ( is_array($data) ) {
  489. sort($data);
  490. }
  491. return $data;
  492. }
  493. /**
  494. * Return all visible form elements
  495. *
  496. * Handle required input attribute
  497. * https://github.com/netzgestaltung/contact-form-7-hooks#filters-in-contact-form-7includescontact-formphp
  498. *
  499. * @return $form_elements
  500. */
  501. function sandbox_wpcf7_form_elements($elements){
  502. return str_replace(' aria-required', ' required aria-required', $elements);
  503. }
  504. /**
  505. * filter values of form tags to email
  506. *
  507. * @param $tag_replace string to change
  508. * @param $submitted an array containing all submitted fields
  509. * @param $cf7_key is a unique string key to identify your form, which you can find in your form table in the dashboard.
  510. */
  511. function sandbox_cf7_mailtag_email_updates($tag_replace, $submitted, $cf7_key){
  512. if ( $cf7_key == 'free-trial' ) {
  513. if ( $tag_replace === '' ) { // empty means no
  514. $tag_replace = 'no'; //change the email-updates.
  515. }
  516. }
  517. return $tag_replace;
  518. }
  519. function sandbox_smart_grid_register_styles(){
  520. // wp_deregister_style('cf7-grid-layout');
  521. }
  522. /**
  523. * filter output of forms to add gated content if custom field is used
  524. */
  525. function sandbox_cf7_gated_content($output, $tag, $attr){
  526. // only for cf7 shortcodes
  527. if( 'contact-form-7' === $tag ){
  528. $form_id = isset($attr['id']) ? $attr['id'] : false;
  529. if ( $form_id ) {
  530. $form_file_download_id = get_post_meta($form_id, '_form-file-download', true);
  531. if ( !empty($form_file_download_id) ) {
  532. $form_file_download_url = wp_get_attachment_url($form_file_download_id);
  533. $form_file_download = get_attached_file($form_file_download_id);
  534. $form_file_path = pathinfo($form_file_download);
  535. $form_file_name = $form_file_path['filename'] . '.' . $form_file_path['extension'];
  536. ob_start();
  537. ?>
  538. <script type="text/javascript">
  539. ;(function(){
  540. document.addEventListener('wpcf7mailsent', function(event){
  541. var download;
  542. if ( event.detail.hasOwnProperty('contactFormId') && parseInt(event.detail.contactFormId) === <?php echo $form_id; ?> ) {
  543. download = document.createElement('a');
  544. download.href = '<?php echo $form_file_download_url; ?>';
  545. download.download = '<?php echo $form_file_name; ?>';
  546. download.click();
  547. }
  548. }, false);
  549. })();
  550. </script>
  551. <?php
  552. $gated_content = ob_get_contents();
  553. ob_end_clean();
  554. $output = $output . $gated_content;
  555. }
  556. }
  557. }
  558. return $output;
  559. }
  560. /**
  561. * Site Widgets
  562. * =============
  563. */
  564. /**
  565. * custom faq navigation widget
  566. * ============================
  567. * requires the post-type "faq"
  568. * requires the taxonomy "topic"
  569. */
  570. class sandbox_faq_nav_widget extends WP_Widget {
  571. public function __construct() {
  572. /* Widget settings. */
  573. $widget_ops = array('classname' => 'faq-navigation', 'description' => 'Displays the FAQ navigation.');
  574. /* Widget control settings. */
  575. $control_ops = array('width' => 300, 'height' => 350, 'id_base' => 'faq-navigation');
  576. /* Create the widget. */
  577. parent::__construct('faq-navigation', 'FAQ Navigation', $widget_ops, $control_ops);
  578. }
  579. // processes widget options to be saved
  580. public function update($new_instance, $old_instance) {
  581. $instance = $old_instance;
  582. $instance['title'] = strip_tags($new_instance['title']);
  583. return $instance;
  584. }
  585. // outputs the content of the widget
  586. public function widget($args, $instance) {
  587. sandbox_faq_nav($args, $instance);
  588. }
  589. // outputs the options form on admin
  590. public function form($instance) {
  591. $title = esc_attr($instance['title']);
  592. ?><p>
  593. <label for="<?php echo $this->get_field_id('title'); ?>"><?php _e('Title:', 'sandbox'); ?></label>
  594. <input class="widefat" id="<?php echo $this->get_field_id('title'); ?>" name="<?php echo $this->get_field_name('title'); ?>" type="text" value="<?php echo $title; ?>" />
  595. </p><?php
  596. }
  597. }
  598. function sandbox_faq_nav($args, $instance){
  599. extract($args);
  600. $widget_title = apply_filters('widget_title', $instance['title']);
  601. /**
  602. * FAQ entries
  603. * grouped by topic
  604. * ordered by menu_order *
  605. */
  606. $faq_ids = get_posts(array(
  607. 'post_type' => 'faq',
  608. 'posts_per_page' => -1,
  609. 'fields' => 'ids',
  610. 'meta_query' => array(
  611. 'relation' => 'OR',
  612. array(
  613. 'key' => '_hide',
  614. 'value' => 1,
  615. 'compare' => 'NOT LIKE',
  616. ),
  617. array(
  618. 'key' => '_hide',
  619. 'value' => 'bug #23268',
  620. 'compare' => 'NOT EXISTS',
  621. )
  622. ),
  623. ));
  624. $topic_term_objects = get_terms(array(
  625. 'taxonomy' => 'topic',
  626. 'object_ids' => $faq_ids,
  627. 'orderby' => 'order', // needs plugin https://github.com/stuttter/wp-term-order/
  628. 'order' => 'ASC',
  629. ));
  630. if ( !empty($topic_term_objects) && !is_wp_error($topic_term_objects) ) {
  631. echo $before_widget;
  632. if ( $widget_title ) {
  633. echo $before_title . $widget_title . $after_title;
  634. }
  635. echo '<ul class="menu menu-faq">';
  636. foreach ( $topic_term_objects as $topic_term_object ) {
  637. $faq_options = array(
  638. 'post_type' => 'faq',
  639. 'tax_query' => array(
  640. array(
  641. 'field' => 'slug',
  642. 'taxonomy' => 'topic',
  643. 'terms' => $topic_term_object->slug,
  644. )
  645. ),
  646. 'meta_query' => array(
  647. 'relation' => 'OR',
  648. array(
  649. 'key' => '_hide',
  650. 'value' => 1,
  651. 'compare' => 'NOT LIKE',
  652. ),
  653. array(
  654. 'key' => '_hide',
  655. 'value' => 'bug #23268',
  656. 'compare' => 'NOT EXISTS',
  657. )
  658. ),
  659. 'posts_per_page' => -1,
  660. 'orderby' => 'menu_order',
  661. 'order' => 'ASC',
  662. );
  663. $faq_query = new WP_Query($faq_options);
  664. if ( $faq_query->have_posts() ) {
  665. echo '<li class="menu-item menu-item-' . esc_attr($topic_term_object->slug) . '">';
  666. echo '<a href="#submenu-' . esc_attr($topic_term_object->slug) . '">' . $topic_term_object->name . '</a>';
  667. echo '<ul id="submenu-' . esc_attr($topic_term_object->slug) . '" class="sub-menu">';
  668. while ( $faq_query->have_posts() ) {
  669. $faq_query->the_post();
  670. $post_id = get_the_ID();
  671. $post_slug = sandbox_get_the_slug();
  672. $post_class = get_post_class();
  673. echo '<li id="menu-item-' . $post_slug . '" class="' . esc_attr(join(' ', $post_class)) . '"><a href="#' . $post_slug . '">' . get_the_title() . '</a></li>';
  674. }
  675. wp_reset_postdata();
  676. echo '</ul></li>';
  677. }
  678. }
  679. echo $after_widget;
  680. }
  681. }
  682. /**
  683. * custom events calender widget
  684. * =============================
  685. * requires the post-type "events" with custom fields:
  686. * -_date-end
  687. * -_date-begin
  688. */
  689. class sandbox_events_widget extends WP_Widget {
  690. public function __construct() {
  691. /* Widget settings. */
  692. $widget_ops = array('classname' => 'events-calendar', 'description' => 'Test um zu schauen ob ich ein widget basteln kann.');
  693. /* Widget control settings. */
  694. $control_ops = array('width' => 300, 'height' => 350, 'id_base' => 'custom-events-calendar');
  695. /* Create the widget. */
  696. parent::__construct('custom-events-calendar', 'N&auml;chste Termine', $widget_ops, $control_ops );
  697. }
  698. // processes widget options to be saved
  699. public function update($new_instance, $old_instance) {
  700. $instance = $old_instance;
  701. $instance['title'] = strip_tags( $new_instance['title'] );
  702. $instance['eventtype'] = $new_instance['eventtype'];
  703. $instance['maximum'] = intval($new_instance['maximum']);
  704. $instance['want_excerpt'] = filter_var($new_instance['want_excerpt'], FILTER_VALIDATE_BOOLEAN);
  705. return $instance;
  706. }
  707. // outputs the content of the widget
  708. public function widget($args, $instance) {
  709. sandbox_events($args, $instance);
  710. }
  711. // outputs the options form on admin
  712. public function form($instance) {
  713. $title = esc_attr($instance['title']);
  714. $eventtypes = get_terms('eventtypen');
  715. $maximum = esc_attr($instance['maximum']);
  716. $want_excerpt = esc_attr($instance['want_excerpt']);
  717. ?>
  718. <p>
  719. <label for="<?php echo $this->get_field_id('title'); ?>"><?php _e('Title:', 'sandbox'); ?></label>
  720. <input class="widefat" id="<?php echo $this->get_field_id('title'); ?>" name="<?php echo $this->get_field_name('title'); ?>" type="text" value="<?php echo $title; ?>" />
  721. </p>
  722. <p>
  723. <label for="<?php echo $this->get_field_id('eventtype'); ?>"><?php _e('Event-Typ:', 'sandbox'); ?></label>
  724. <select class="widefat" id="<?php echo $this->get_field_id('eventtype'); ?>" name="<?php echo $this->get_field_name('eventtype'); ?>">
  725. <?php foreach ($eventtypes as $eventtype){ ?>
  726. <option value="<?php echo $eventtype->slug; ?>"<?php if ( $instance['eventtype'] == $eventtype->slug ) { echo ' selected="selected"'; } ?>><?php echo $eventtype->name; ?></option>
  727. <?php } ?>
  728. </select>
  729. </p>
  730. <p>
  731. <label for="<?php echo $this->get_field_id('maximum'); ?>"><?php _e('Maximum:', 'sandbox'); ?></label>
  732. <input class="widefat" id="<?php echo $this->get_field_id('maximum'); ?>" name="<?php echo $this->get_field_name('maximum'); ?>" type="text" value="<?php echo $maximum; ?>" />
  733. </p>
  734. <p>
  735. <input class="checkbox" type="checkbox" value="true" <?php checked( 1, $want_excerpt ); ?> id="<?php echo $this->get_field_id('want_excerpt'); ?>" name="<?php echo $this->get_field_name('want_excerpt'); ?>" />
  736. <label for="<?php echo $this->get_field_id('want_excerpt'); ?>"><?php _e('Auszug anzeigen', 'sandbox'); ?></label>
  737. </p>
  738. <?php
  739. }
  740. }
  741. function sandbox_events($args, $instance){
  742. extract($args);
  743. $title = apply_filters('widget_title', $instance['title'] );
  744. $max = $instance['maximum'];
  745. $index = 0;
  746. $eventsQuery = array(
  747. 'post_type' => 'events',
  748. 'order' => 'ASC',
  749. 'orderby' => 'meta_value',
  750. 'meta_key' => '_date-begin',
  751. 'eventtypen' => $instance['eventtype'],
  752. 'posts_per_page' => 100,
  753. );
  754. $events = new WP_Query($eventsQuery);
  755. $want_excerpt = $instance['want_excerpt'];
  756. if ( $events->have_posts() ) {
  757. echo $before_widget;
  758. if ( $title ) { echo $before_title . $title . $after_title; }
  759. echo '<ul class="events events-widget">';
  760. while ( $events->have_posts() ) {
  761. $events->the_post();
  762. if ( $index < $max ) {
  763. $event_meta = get_post_meta(get_the_ID());
  764. $target_day = isset($event_meta["_date-end"][0]) && is_string($event_meta["_date-end"][0]) && strlen($event_meta["_date-end"][0]) > 0 ? $event_meta["_date-end"][0] : $event_meta["_date-begin"][0];
  765. $current_date = $date = date('Y-m-d', time());
  766. // DEBUG
  767. // echo '<!-- title:', get_the_title(), ', max: ', $max, ', index: ', $index + 1, ' -->';
  768. // echo '<!-- title:', get_the_title(), ' ', $current_date, ' lte ', $target_day, ' === ', var_dump( $current_date <= $target_day ), ' -->';
  769. if ( $current_date <= $target_day ) {
  770. $index++;
  771. $begin_dayDisplay = date("j. n.", strtotime($event_meta["_date-begin"][0]));
  772. $begin_yearDisplay = date("Y", strtotime($event_meta["_date-begin"][0]));
  773. ?>
  774. <li <?php post_class('clearfix'); ?>>
  775. <aside class="meta"><p class="date"><span class="day"><?php echo $begin_dayDisplay; ?></span> <span class="year"><?php echo $begin_yearDisplay; ?></span></p></aside>
  776. <h4><a href="<?php the_permalink() ?>"><span class="entry-title"><?php the_title() ?></span></a></h4>
  777. <?php if ( $want_excerpt && has_excerpt() ) { ?>
  778. <div class="entry-summary">
  779. <?php the_excerpt(); ?>
  780. </div>
  781. <?php } ?>
  782. </li>
  783. <?php
  784. }
  785. }
  786. }
  787. echo '</ul>';
  788. echo $after_widget;
  789. }
  790. wp_reset_postdata();
  791. }
  792. /**
  793. * custom social share widget
  794. * ==========================
  795. * No user tracking, no javascript.
  796. *
  797. * - to use in your themes function.php
  798. * - edit the markup of the widget at sandbox_social();
  799. * - add your services at update()
  800. * - Service adresses are hardcoded and can change during time
  801. * - Add the CSS part of this file in yourThemes style.css
  802. */
  803. class sandbox_social_widget extends WP_Widget {
  804. public function __construct() {
  805. /* Widget settings. */
  806. $widget_ops = array('classname' => 'social', 'description' => 'Display social share icons without automatic user tracking');
  807. /* Widget control settings. */
  808. $control_ops = array('width' => 300, 'height' => 350, 'id_base' => 'social');
  809. /* Create the widget. */
  810. parent::__construct('social', 'Social share', $widget_ops, $control_ops );
  811. }
  812. // processes widget options to be saved
  813. public function update($new_instance, $old_instance) {
  814. $new_instance = (array) $new_instance;
  815. $instance = array(
  816. 'title' => strip_tags( $new_instance['title'] ),
  817. 'services' => array(
  818. 'xing' => array(
  819. 'name' => 'XING',
  820. 'url' => 'https://www.xing.com/spi/shares/new?url=',
  821. ),
  822. 'facebook' => array(
  823. 'name' => 'Facebook',
  824. 'url' => 'https://www.facebook.com/sharer/sharer.php?u=',
  825. ),
  826. 'twitter' => array(
  827. 'name' => 'Twitter',
  828. 'url' => 'http://twitter.com/share?url=',
  829. ),
  830. 'googleplus' => array(
  831. 'name' => 'Google+',
  832. 'url' => 'https://plus.google.com/share?url=',
  833. ),
  834. 'linkedin' => array(
  835. 'name' => 'LinkedIn',
  836. 'url' => 'http://www.linkedin.com/sharer.php?u=',
  837. ),
  838. 'pinterest' => array(
  839. 'name' => 'Pinterest',
  840. 'url' => 'http://www.pinterest.com/pin/create/bookmarklet/?url=',
  841. ),
  842. 'email' => array(
  843. 'name' => 'Email',
  844. 'url' => 'mailto:?subject=' . __('Teilen mit', 'sandbox') . ' ' . wp_get_document_title() . '&body=',
  845. ),
  846. ),
  847. );
  848. foreach ( $instance['services'] as $serviceName => $serviceData ) {
  849. $instance[$serviceName] = filter_var($new_instance[$serviceName], FILTER_VALIDATE_BOOLEAN);
  850. }
  851. return $instance;
  852. }
  853. // outputs the content of the widget
  854. public function widget($args, $instance) {
  855. sandbox_social($args, $instance);
  856. }
  857. // outputs the options form on admin
  858. public function form($instance) {
  859. $defaults = array('facebook' => true, 'twitter' => true, 'googleplus' => true, 'linkedin' => false);
  860. $services = $instance['services'];
  861. $instance = wp_parse_args( (array) $instance, $defaults);
  862. $title = esc_attr($instance['title']);
  863. ?>
  864. <p>
  865. <label for="<?php echo $this->get_field_id('title'); ?>"><?php _e('Title:', 'sandbox'); ?></label>
  866. <input class="widefat" id="<?php echo $this->get_field_id('title'); ?>" name="<?php echo $this->get_field_name('title'); ?>" type="text" value="<?php echo $title; ?>" />
  867. </p>
  868. <?php foreach ( $services as $serviceName => $serviceData ) { ?>
  869. <p>
  870. <input class="checkbox" value="true" type="checkbox" id="<?php echo $this->get_field_id($serviceName); ?>" name="<?php echo $this->get_field_name($serviceName); ?>" <?php checked($instance[$serviceName], true) ?> />
  871. <label for="<?php echo $this->get_field_id($serviceName); ?>"><?php echo $serviceData['name']; ?></label>
  872. </p>
  873. <?php } ?>
  874. <?php
  875. }
  876. }
  877. function sandbox_social($args, $instance){
  878. extract($args);
  879. $title = apply_filters('widget_title', $instance['title'] );
  880. $services = $instance['services'];
  881. $protocol = strpos(strtolower($_SERVER['SERVER_PROTOCOL']),'https') === false ? 'http' : 'https';
  882. $host = $_SERVER["HTTP_HOST"];
  883. $path = $_SERVER["REQUEST_URI"];
  884. $pageUrl = $protocol . '://' . $host . $path;
  885. $servicesCount = 0;
  886. $servicesList = '';
  887. foreach ( $services as $serviceName => $serviceData ) {
  888. if ( $instance[$serviceName] ) {
  889. $servicesCount++;
  890. $servicesList .= '<li class="' . $serviceName . '"><a href="' . esc_url($serviceData["url"], ( $serviceName === 'email' ? 'mailto' : 'https' ) ) . $pageUrl . '" target="_blank" title="' . __('Teilen mit', 'sandbox') . ' ' . $serviceData["name"] . '">' . $serviceData["name"] . '</a></li>';
  891. }
  892. }
  893. if ( $servicesCount > 0 ) {
  894. echo $before_widget;
  895. ?>
  896. <div class="social">
  897. <?php if ( !empty($title) ) { echo $before_title . $title . $after_title; } ?>
  898. <ul>
  899. <?php echo $servicesList; ?>
  900. </ul>
  901. </div>
  902. <?php
  903. echo $after_widget;
  904. }
  905. }
  906. /**
  907. * custom slider widget
  908. */
  909. class sandbox_slider_widget extends WP_Widget {
  910. function __construct() {
  911. /* Widget settings. */
  912. $widget_ops = array('classname' => 'slider', 'description' => 'Select a slider to display');
  913. /* Widget control settings. */
  914. $control_ops = array('width' => 300, 'height' => 350, 'id_base' => 'slider');
  915. /* Create the widget. */
  916. parent::__construct('slider', 'Slider', $widget_ops, $control_ops );
  917. }
  918. // processes widget options to be saved
  919. public function update($new_instance, $old_instance) {
  920. $instance = $old_instance;
  921. $instance['title'] = strip_tags( $new_instance['title'] );
  922. $instance['slider'] = $new_instance['slider'];
  923. $instance['show-titles'] = filter_var($new_instance['show-titles'], FILTER_VALIDATE_BOOLEAN);
  924. $instance['show-content'] = filter_var($new_instance['show-content'], FILTER_VALIDATE_BOOLEAN);
  925. $instance['show-excerpt'] = filter_var($new_instance['show-excerpt'], FILTER_VALIDATE_BOOLEAN);
  926. return $instance;
  927. }
  928. // outputs the content of the widget
  929. public function widget($args, $instance) {
  930. sandbox_slider($args, $instance);
  931. }
  932. // outputs the options form on admin
  933. public function form($instance) {
  934. $title = esc_attr($instance['title']);
  935. $sliders = get_terms('slider');
  936. ?>
  937. <p>
  938. <label for="<?php echo $this->get_field_id('title'); ?>"><?php _e('Title:', 'sandbox'); ?></label>
  939. <input class="widefat" id="<?php echo $this->get_field_id('title'); ?>" name="<?php echo $this->get_field_name('title'); ?>" type="text" value="<?php echo $title; ?>" />
  940. </p>
  941. <p>
  942. <label for="<?php echo $this->get_field_id('slider'); ?>"><?php _e('Slider:', 'sandbox'); ?></label>
  943. <select class="widefat" id="<?php echo $this->get_field_id('slider'); ?>" name="<?php echo $this->get_field_name('slider'); ?>">
  944. <?php foreach ($sliders as $slider){ ?>
  945. <option value="<?php echo $slider->slug; ?>"<?php if ( $instance['slider'] == $eventtype->slug ) { echo ' selected="selected"'; } ?>><?php echo $slider->name; ?></option>
  946. <?php } ?>
  947. </select>
  948. </p>
  949. <p>
  950. <input class="checkbox" value="true" type="checkbox" id="<?php echo $this->get_field_id('show-titles'); ?>" name="<?php echo $this->get_field_name('show-titles'); ?>" <?php checked($instance['show-titles'], true) ?> />
  951. <label for="<?php echo $this->get_field_id('show-titles'); ?>"><?php echo 'Show titles'; ?></label>
  952. </p>
  953. <p>
  954. <input class="checkbox" value="true" type="checkbox" id="<?php echo $this->get_field_id('show-content'); ?>" name="<?php echo $this->get_field_name('show-content'); ?>" <?php checked($instance['show-content'], true) ?> />
  955. <label for="<?php echo $this->get_field_id('show-content'); ?>"><?php echo 'Show content'; ?></label>
  956. </p>
  957. <p>
  958. <input class="checkbox" value="true" type="checkbox" id="<?php echo $this->get_field_id('show-excerpt'); ?>" name="<?php echo $this->get_field_name('show-excerpt'); ?>" <?php checked($instance['show-excerpt'], true) ?> />
  959. <label for="<?php echo $this->get_field_id('show-excerpt'); ?>"><?php echo 'Show excerpt'; ?></label>
  960. </p>
  961. <?php
  962. }
  963. }
  964. function sandbox_slider($args, $instance){
  965. extract($args);
  966. $title = apply_filters('widget_title', $instance['title']);
  967. $sliderQuery = array(
  968. 'post_type' => 'slide',
  969. 'order' => 'ASC',
  970. 'orderby' => 'menu_order',
  971. 'slider' => $instance['slider']
  972. );
  973. $slider = new WP_Query($sliderQuery);
  974. $sliderCount = 0;
  975. $sliderNav = '<ul class="slider-nav">';
  976. $sliderId = $slider->query_vars['taxonomy'] . '-' . $slider->query_vars['term'];
  977. $sliderClass = $slider->query_vars['taxonomy'];
  978. $show_titles = filter_var($instance['show-titles'], FILTER_VALIDATE_BOOLEAN);
  979. $show_content = filter_var($instance['show-content'], FILTER_VALIDATE_BOOLEAN);
  980. $show_excerpt = filter_var($instance['show-excerpt'], FILTER_VALIDATE_BOOLEAN);
  981. if ( $slider->have_posts() ) {
  982. echo $before_widget;
  983. echo '<section class="', $sliderClass, ' ', $sliderId, '" id="', $sliderId, '">';
  984. if ( $title ){ echo $before_title . $title . $after_title; }
  985. echo ' <ul class="slides clearfix">';
  986. while ( $slider->have_posts() ) { $slider->the_post();
  987. $slideId = get_post_field('post_name', get_the_ID() );
  988. $sliderCount++;
  989. $sliderNav .= '<li><a href="#slide-' . $slideId . '">' . $sliderCount . '</a></li>';
  990. $sliderImage = get_the_post_thumbnail(get_the_ID(), 'slider', array('title' => the_title_attribute('echo=0')));
  991. $sliderMeta = get_post_meta( get_the_ID() );
  992. $the_content = $show_content ? get_the_content() : $show_content;
  993. $has_content = !empty(trim(str_replace('&nbsp;', '', strip_tags($the_content))));
  994. // echo var_dump($sliderMeta["slider-link"][0]);
  995. ?>
  996. <li id="slide-<?php echo $slideId ?>" class="slide slide-<?php echo $slideId ?> slide-<?php echo $sliderCount ?> clearfix">
  997. <?php echo $sliderImage; ?>
  998. <?php if ( $show_titles || $show_excerpt || $show_content ) { ?>
  999. <div class="inner">
  1000. <?php if ( $show_titles ) { ?>
  1001. <h3><?php the_title(); ?></h3>
  1002. <?php } ?>
  1003. <?php if ( $show_content && $has_content ) { ?>
  1004. <div class="content">
  1005. <?php the_content(); ?>
  1006. </div>
  1007. <?php } ?>
  1008. <?php if ( $show_excerpt && has_excerpt() ) { ?>
  1009. <div class="content excerpt">
  1010. <?php the_excerpt(); ?>
  1011. </div>
  1012. <?php } ?>
  1013. </div>
  1014. <?php } ?>
  1015. </li>
  1016. <?php
  1017. }
  1018. echo '</ul>';
  1019. $sliderNav .= '</ul>';
  1020. echo $sliderNav;
  1021. echo '</section>';
  1022. echo $after_widget;
  1023. }
  1024. wp_reset_postdata();
  1025. }
  1026. ?>