PluginProbe
MM Title Manager — Hide Page and Post Titles / 1.10
MM Title Manager — Hide Page and Post Titles v1.10
1.12 1.11 trunk 1.10 1.10.1 1.8.2 1.8.3 1.8.4 1.8.5 1.8.6 1.8.7 1.8.8 1.9 1.9.1
hide-titles / hide-titles.php

hide-titles.php in MM Title Manager — Hide Page and Post Titles 1.10, at hide-titles.php

381 lines 16.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Plugin Name: MM Title Manager
5 * Plugin URI: https://wordpress.org/plugins/hide-titles/
6 * Description: Remove Titles from Posts and Single Pages on WordPress.
7 * Version: 1.10
8 * Requires at least: 4.4
9 * Requires PHP: 5.6
10 * Tested up to: 7.0
11 * Author: Mehraz Morshed
12 * Author URI: https://profiles.wordpress.org/mehrazmorshed/
13 * License: GPL v2 or later
14 * License URI: https://www.gnu.org/licenses/gpl-2.0.html
15 * Text Domain: hide-titles
16 * Domain Path: /languages
17 */
18
19 /**
20 * Hide Titles is free software: you can redistribute it and/or
21 * modify it under the terms of the GNU General Public License
22 * as published by the Free Software Foundation, either version 3
23 * of the License, or (at your option) any later version.
24 *
25 * Hide Titles is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 *
30 * You should have received a copy of the GNU General Public License
31 * along with this program. If not, see <https://www.gnu.org/licenses/>.
32 */
33
34 // Exit if accessed directly
35 if ( ! defined( 'ABSPATH' ) ) {
36 exit;
37 }
38
39 // Load the text-domain
40 function hide_titles_load_textdomain() {
41 load_plugin_textdomain( 'hide-titles', false, dirname( plugin_basename( __FILE__ ) ) . '/languages' );
42 }
43 add_action( 'init', 'hide_titles_load_textdomain' );
44
45 function hide_titles_option_page() {
46
47 add_menu_page( __( 'MM Title Manager', 'hide-titles' ), __( 'MM Title Manager', 'hide-titles' ), 'manage_options', 'hide-titles', 'hide_titles_create_page', 'dashicons-heading', 101 );
48 }
49 add_action( 'admin_menu', 'hide_titles_option_page' );
50
51 function hide_titles_style_settings( $hook_suffix ) {
52
53 $screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null;
54 if ( ! $screen ) {
55 return;
56 }
57
58 $screens = array( 'toplevel_page_hide-titles', 'post', 'page' );
59 if ( ! in_array( $screen->id, $screens, true ) ) {
60 return;
61 }
62
63 wp_enqueue_style( 'hide-titles-admin', plugins_url( 'css/hide-titles-settings.css', __FILE__ ), array(), '1.9.2' );
64 }
65 add_action( 'admin_enqueue_scripts', 'hide_titles_style_settings' );
66
67 function hide_titles_create_page() {
68 $current = get_option( 'hide-titles-option', 'nothing' );
69 ?>
70 <div class="hide_titles_main">
71 <div class="hide_titles_body hide_titles_common">
72 <header class="ht-mm-hero">
73 <p class="ht-mm-hero__eyebrow"><?php esc_html_e( 'MM Title Manager', 'hide-titles' ); ?></p>
74 <h1 class="ht-mm-hero__title" id="page-title"><?php esc_html_e( 'Title visibility', 'hide-titles' ); ?></h1>
75 <p class="ht-mm-hero__lead"><?php esc_html_e( 'Control titles on single posts and pages. Navigation menus always keep their labels.', 'hide-titles' ); ?></p>
76 </header>
77
78 <form class="ht-mm-form" action="options.php" method="post">
79 <?php wp_nonce_field( 'update-options' ); ?>
80
81 <fieldset class="ht-mm-fieldset">
82 <legend class="ht-mm-fieldset__legend"><?php esc_html_e( 'Global behavior', 'hide-titles' ); ?></legend>
83 <p class="ht-mm-fieldset__hint"><?php esc_html_e( 'Applies site-wide unless you override per post or page in the editor.', 'hide-titles' ); ?></p>
84
85 <div class="ht-mm-options">
86 <label class="ht-mm-card">
87 <input type="radio" name="hide-titles-option" id="hide-titles-option-nothing" value="nothing" <?php checked( $current, 'nothing' ); ?>>
88 <span class="ht-mm-card__icon dashicons dashicons-visibility" aria-hidden="true"></span>
89 <span class="ht-mm-card__text">
90 <strong class="ht-mm-card__title"><?php esc_html_e( 'Show all titles', 'hide-titles' ); ?></strong>
91 <span class="ht-mm-card__desc"><?php esc_html_e( 'Default WordPress title output everywhere.', 'hide-titles' ); ?></span>
92 </span>
93 </label>
94
95 <label class="ht-mm-card">
96 <input type="radio" name="hide-titles-option" id="hide-titles-option-all" value="all" <?php checked( $current, 'all' ); ?>>
97 <span class="ht-mm-card__icon dashicons dashicons-no-alt" aria-hidden="true"></span>
98 <span class="ht-mm-card__text">
99 <strong class="ht-mm-card__title"><?php esc_html_e( 'Hide all titles', 'hide-titles' ); ?></strong>
100 <span class="ht-mm-card__desc"><?php esc_html_e( 'Removes titles in templates; menus still show link text.', 'hide-titles' ); ?></span>
101 </span>
102 </label>
103 </div>
104 </fieldset>
105
106 <input type="hidden" name="action" value="update">
107 <input type="hidden" name="page_options" value="hide-titles-option">
108
109 <p class="ht-mm-actions">
110 <button type="submit" name="submit" class="button button-primary button-hero ht-mm-submit"><?php esc_html_e( 'Save changes', 'hide-titles' ); ?></button>
111 </p>
112 </form>
113
114 <section class="ht-mm-tip" aria-labelledby="ht-mm-per-post-heading">
115 <h2 id="ht-mm-per-post-heading" class="ht-mm-tip__title"><?php esc_html_e( 'Per post or page', 'hide-titles' ); ?></h2>
116 <p class="ht-mm-tip__text"><?php esc_html_e( 'Edit any post or page and use the Hide Titles box in the sidebar to hide only that item’s title. Menu labels stay visible.', 'hide-titles' ); ?></p>
117 <figure class="ht-mm-tip__figure">
118 <img class="screenshot" src="<?php echo esc_url( plugin_dir_url( __FILE__ ) . 'img/single.png' ); ?>" alt="">
119 </figure>
120 </section>
121 </div>
122 <div class="hide_titles_aside hide_titles_common">
123 <!-- about plugin author -->
124 <h2 class="aside-title"><?php esc_html_e( 'About Plugin Author', 'hide-titles' ); ?></h2>
125 <div class="author-card">
126 <a class="link" href="https://profiles.wordpress.org/mehrazmorshed/" target="_blank">
127 <img class="center" src="<?php echo esc_url( plugin_dir_url( __FILE__ ) . 'img/author.png' ); ?>" width="128" height="128" alt="">
128 <h3 class="author-title"><?php esc_html_e( 'Mehraz Morshed', 'hide-titles' ); ?></h3>
129 <h4 class="author-title"><?php esc_html_e( 'WordPress Developer', 'hide-titles' ); ?></h4>
130 </a>
131 <h1 class="author-title">
132 <a class="link" href="https://www.facebook.com/mehrazmorshed" target="_blank"><span class="dashicons dashicons-facebook"></span></a>
133 <a class="link" href="https://twitter.com/mehrazmorshed" target="_blank"><span class="dashicons dashicons-twitter"></span></a>
134 <a class="link" href="https://www.linkedin.com/in/mehrazmorshed" target="_blank"><span class="dashicons dashicons-linkedin"></span></a>
135 <a class="link" href="https://www.youtube.com/@mehrazmorshed" target="_blank"><span class="dashicons dashicons-youtube"></span></a>
136 </h1>
137 </div>
138 <!-- other useful plugins -->
139 <h3 class="aside-title"><?php esc_html_e( 'Other Useful Plugins', 'hide-titles' ); ?></h3>
140 <div class="author-card">
141 <a class="link" href="https://wordpress.org/plugins/turn-off-comments/" target="_blank">
142 <span class="dashicons dashicons-admin-plugins"></span> <b><?php _e( 'Disable Comments', 'hide-titles' ) ?></b>
143 </a>
144 <hr>
145 <a class="link" href="https://wordpress.org/plugins/hide-admin-navbar/" target="_blank">
146 <span class="dashicons dashicons-admin-plugins"></span> <b><?php _e( 'Hide Admin Toolbar', 'hide-titles' ) ?></b>
147 </a>
148 <hr>
149 <a class="link" href="https://wordpress.org/plugins/about-post-author/" target="_blank">
150 <span class="dashicons dashicons-admin-plugins"></span> <b><?php _e( 'Simple Author Box', 'hide-titles' ) ?></b>
151 </a>
152 </div>
153 <!-- donate to this plugin -->
154 <h3 class="aside-title"><?php esc_html_e( 'Support', 'hide-titles' ); ?></h3>
155 <a class="link" href="https://www.buymeacoffee.com/mehrazmorshed" target="_blank" rel="noopener noreferrer">
156 <button type="button" class="button button-primary btn"><?php esc_html_e( 'Donate to this plugin', 'hide-titles' ); ?></button>
157 </a>
158 <p class="ht-mm-or"><span><?php esc_html_e( 'or', 'hide-titles' ); ?></span></p>
159 <a class="link" href="https://wordpress.org/support/plugin/hide-titles/reviews/#new-post" target="_blank" rel="noopener noreferrer">
160 <button type="button" class="button button-secondary btn"><?php esc_html_e( 'Leave a review', 'hide-titles' ); ?></button>
161 </a>
162 </div>
163 </div>
164
165 <?php
166 }
167
168 if( get_option( 'hide-titles-option' ) == 'all' ) {
169
170 function hide_titles() {
171
172 return false;
173 }
174 add_filter('the_title', 'hide_titles');
175 }
176
177 function hide_titles_plugin_activation() {
178
179 add_option( 'hide_titles_plugin_do_activation_redirect', true );
180 }
181 register_activation_hook( __FILE__, 'hide_titles_plugin_activation' );
182
183 function hide_titles_plugin_redirect() {
184
185 if( get_option( 'hide_titles_plugin_do_activation_redirect', false ) ) {
186
187 delete_option( 'hide_titles_plugin_do_activation_redirect' );
188
189 if ( !isset( $_GET['active-multi'] ) ) {
190
191 wp_safe_redirect( admin_url( 'admin.php?page=hide-titles' ) );
192 exit;
193 }
194 }
195 }
196 add_action( 'admin_init', 'hide_titles_plugin_redirect' );
197 /*********************************************************************/
198 add_action('add_meta_boxes', 'hide_titles_meta_box');
199 add_action('save_post', 'hide_titles_save_meta');
200 add_filter( 'the_title', 'hide_titles_filter_title', 10, 2 );
201 add_filter( 'nav_menu_item_title', 'hide_titles_restore_nav_menu_title', 10, 4 );
202
203 /**
204 * Restore menu link text when titles are hidden via the_title.
205 *
206 * WordPress runs post titles through `the_title` when building menu items
207 * (see wp_setup_nav_menu_item). Without this, hidden titles become blank
208 * or “no title” in menus. We keep the stored navigation label or the raw
209 * post title for display in menus only.
210 *
211 * @param string $title The menu item’s title.
212 * @param object $menu_item The menu item object.
213 * @param stdClass $args An object of wp_nav_menu() arguments.
214 * @param int $depth Depth of menu item.
215 * @return string
216 */
217 function hide_titles_restore_nav_menu_title( $title, $menu_item, $args, $depth ) {
218
219 if ( ! is_object( $menu_item ) || 'post_type' !== $menu_item->type || empty( $menu_item->object_id ) ) {
220 return $title;
221 }
222
223 $object_id = (int) $menu_item->object_id;
224 if ( $object_id < 1 ) {
225 return $title;
226 }
227
228 $hide_globally = ( get_option( 'hide-titles-option' ) === 'all' );
229 $hide_per_post = ( get_post_meta( $object_id, '_hide_title', true ) === 'on' );
230
231 if ( ! $hide_globally && ! $hide_per_post ) {
232 return $title;
233 }
234
235 if ( isset( $menu_item->post_title ) && '' !== $menu_item->post_title ) {
236 return $menu_item->post_title;
237 }
238
239 $raw = get_post_field( 'post_title', $object_id, 'raw' );
240
241 return ( is_string( $raw ) && '' !== $raw ) ? $raw : $title;
242 }
243
244 // Add meta box to hide title
245 function hide_titles_meta_box() {
246 add_meta_box( 'hide-title-meta-box', __( 'MM Title Manager', 'hide-titles' ), 'hide_titles_meta_box_callback', array( 'post', 'page' ), 'side', 'default' );
247 }
248
249 // Meta box callback function
250 function hide_titles_meta_box_callback($post) {
251 $value = get_post_meta($post->ID, '_hide_title', true);
252 wp_nonce_field( 'hide_titles_meta_save', 'hide_titles_meta_nonce' );
253 ?>
254 <div class="ht-mm-meta">
255 <label class="ht-mm-meta__toggle" for="hide-titles-checkbox">
256 <input type="checkbox" id="hide-titles-checkbox" name="hide_titles_checkbox" <?php checked( $value, 'on' ); ?> />
257 <span class="ht-mm-meta__label"><?php esc_html_e( 'Hide title on this page', 'hide-titles' ); ?></span>
258 </label>
259 <p class="ht-mm-meta__hint"><?php esc_html_e( 'Hides the title in the content area only. Navigation menus and the admin list keep their titles.', 'hide-titles' ); ?></p>
260 <p class="ht-mm-meta__review"><a href="https://wordpress.org/support/plugin/hide-titles/reviews/#new-post" target="_blank" rel="noopener noreferrer"><?php esc_html_e( 'Leave a review', 'hide-titles' ); ?></a></p>
261 </div>
262 <?php
263 }
264
265 // Save meta box data
266 function hide_titles_save_meta($post_id) {
267 if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
268 return;
269 }
270 if ( ! isset( $_POST['hide_titles_meta_nonce'] ) || ! wp_verify_nonce( wp_unslash( $_POST['hide_titles_meta_nonce'] ), 'hide_titles_meta_save' ) ) {
271 return;
272 }
273 if ( ! current_user_can( 'edit_post', $post_id ) ) {
274 return;
275 }
276 if ( array_key_exists( 'hide_titles_checkbox', $_POST ) ) {
277 update_post_meta( $post_id, '_hide_title', 'on' );
278 } else {
279 delete_post_meta( $post_id, '_hide_title' );
280 }
281 }
282
283 // Filter the title to hide it
284 function hide_titles_filter_title($title, $id = null) {
285 if (is_admin() || !$id) {
286 return $title;
287 }
288
289 $hide_title = get_post_meta($id, '_hide_title', true);
290 if ($hide_title === 'on') {
291 return '';
292 }
293
294 return $title;
295 }
296
297
298
299
300
301 /**
302 * Save installation datetime on plugin activation
303 */
304 function hide_titles_activate() {
305 // Check if the installation time is already saved
306 $installed = get_option('hide_titles_installed');
307
308 if (!$installed) {
309 // Save current datetime if not already set
310 update_option('hide_titles_installed', current_time('mysql'));
311 }
312 }
313 register_activation_hook(__FILE__, 'hide_titles_activate');
314
315 /**
316 * Clean up options on plugin uninstallation
317 */
318 function hide_titles_uninstall() {
319 delete_option('hide_titles_installed');
320 }
321 register_uninstall_hook(__FILE__, 'hide_titles_uninstall');
322
323 /**
324 * Show migration notice for installations before Oct 30, 2025
325 */
326 function ht_show_migration_notice() {
327 // Only show if new plugin is not active
328 if (is_plugin_active('daisy-titles/daisy-titles.php')) {
329 return;
330 }
331
332 // Get installation date
333 $install_date = get_option('hide_titles_installed');
334
335 // Only show notice if:
336 // 1. There is NO install date (new installation) OR
337 // 2. Installation date is BEFORE Oct 30, 2025
338 if ($install_date && strtotime($install_date) >= strtotime('2025-10-30')) {
339 return;
340 }
341
342 // Get install/activate URLs
343 $install_url = wp_nonce_url(
344 add_query_arg([
345 'action' => 'install-plugin',
346 'plugin' => 'daisy-titles'
347 ], admin_url('update.php')),
348 'install-plugin_daisy-titles'
349 );
350
351 $activate_url = '';
352 if (file_exists(WP_PLUGIN_DIR . '/daisy-titles/daisy-titles.php')) {
353 $activate_url = wp_nonce_url(
354 add_query_arg([
355 'action' => 'activate',
356 'plugin' => 'daisy-titles/daisy-titles.php'
357 ], admin_url('plugins.php')),
358 'activate-plugin_daisy-titles/daisy-titles.php'
359 );
360 }
361 ?>
362 <div class="notice notice-error">
363 <h4><?php esc_html_e('Important Notice About Hide Titles', 'hide-titles'); ?></h4>
364 <p>
365 <?php _e('This plugin is no longer maintained. Please migrate to our new improved plugin <b style="color: blue;">"Daisy Titles"</b> for continued support, new features, and future updates.', 'hide-titles'); ?>
366 </p>
367 <p>
368 <?php if ($activate_url) : ?>
369 <a href="<?php echo esc_url($activate_url); ?>" class="button button-primary">
370 <?php esc_html_e('Activate Daisy Titles Now', 'hide-titles'); ?>
371 </a>
372 <?php else : ?>
373 <a href="<?php echo esc_url($install_url); ?>" class="button button-primary">
374 <?php esc_html_e('Migrate to Daisy Titles Now', 'hide-titles'); ?>
375 </a>
376 <?php endif; ?>
377 </p>
378 </div>
379 <?php
380 }
381 add_action('admin_notices', 'ht_show_migration_notice');