• Resolved iboone

    (@iboone)


    This plugins generates php failure under php 5.4 due to the fact that the code use array syntaxes like [] instead of array().
    In order to make it work on my server, I had to replace

    every [] with “array()”
    and
    every [“variable x”,”variable y”] with array(“variable x”,”variable y”)

    in media-sync.php & in MediaSync.class.php

    I can send my files if you need to.

Viewing 4 replies - 1 through 4 (of 4 total)
  • Thread Starter iboone

    (@iboone)

    media-sync.php retrocompatibility

    <?php
    
    /**
     * Plugin Name: Media Sync
     * Plugin URI: https://wordpress.org/plugins/media-sync/
     * Description: Simple plugin to scan uploads directory and bring files to Media Library
     * Version: 0.1.5
     * Author: Erol Živina
     * Author URI: https://github.com/erolsk8
     * License: GPLv2+
     * License URI: https://www.gnu.org/licenses/gpl-2.0.html
     * Text Domain: media-sync
     * Domain Path: /languages
     *
     */
    
    // Exit if accessed directly
    if ( ! defined( 'ABSPATH' ) ) exit;
    
    add_filter( 'plugin_action_links_' . plugin_basename(__FILE__), 'media_sync_link_to_main_plugin_page' );
    
    /**
     * Add link below plugin name on 'Plugins' page
     *
     * @since 0.1.0
     */
    function media_sync_link_to_main_plugin_page( $links ) {
        $title = __('Media Sync', 'media-sync');
        $links[] = '<a href="'. esc_url( get_admin_url(null, 'upload.php?page=media-sync-page') ) .'">' . $title . '</a>';
        return $links;
    }
    
    add_action( 'admin_menu', 'media_sync_add_menu_items' );
    
    /**
     * Add menu item for this plugin
     *
     * @since 0.1.0
     */
    function media_sync_add_menu_items() {
        $title = __('Media Sync', 'media-sync');
        // Add sub item to Media menu
        add_media_page( $title, $title, 'activate_plugins', 'media-sync-page', 'media_sync_main_page' );
    }
    
    include( plugin_dir_path(__FILE__) . 'includes/MediaSync.class.php');
    
    add_action( 'admin_enqueue_scripts', 'media_sync_load_admin_scripts', 100 );
    
    /**
     * Load Admin CSS and JS files
     *
     * @since 0.1.0
     * @return void
     */
    function media_sync_load_admin_scripts( $hook ) {
    
        $js_dir  = plugin_dir_url( __FILE__ ) . 'admin/js/';
        $css_dir = plugin_dir_url( __FILE__ ) . 'admin/css/';
    
        wp_register_script( 'media-sync-js-admin-script', $js_dir . 'script.js', array('jquery'), false, true );
        wp_enqueue_script( 'media-sync-js-admin-script' );
    
        wp_enqueue_script( 'media-sync-js-admin-ajax-script', $js_dir . 'ajax_script.js', array('jquery') );
        wp_localize_script( 'media-sync-js-admin-ajax-script', 'ajax_data', array(
            'ajax_url' => admin_url( 'admin-ajax.php' ),
            'security' => wp_create_nonce( "media_sync_import_files" )
        ));
    
        wp_register_style( 'media-sync-css-admin-style', $css_dir . 'style.css');
        wp_enqueue_style( 'media-sync-css-admin-style' );
    }
    
    add_action( 'wp_ajax_media_sync_import_files', 'media_sync_import_files' );
    
    /**
     * Ajax action to import selected file
     *
     * @since 0.1.0
     * @return void
     */
    function media_sync_import_files() {
        MediaSync::media_sync_import_files();
    }
    
    add_action( 'plugins_loaded', 'media_sync_load_plugin_textdomain' );
    
    /**
     * Loads plugin translated strings
     *
     * @since 0.1.4
     * @return void
     */
    function media_sync_load_plugin_textdomain() {
        load_plugin_textdomain( 'media-sync', false, dirname( plugin_basename( __FILE__ ) ) . '/languages' );
    }
    
    /**
     * Main function for "Media Sync" page
     *
     * @since 0.1.0
     * @return void
     */
    function media_sync_main_page() {
        MediaSync::media_sync_main_page();
    }
    Thread Starter iboone

    (@iboone)

    MediaSync.class.php retrocompatibility

    <?php
    
    /**
     * Media Sync
     *
     * This class is used for generating main content and also to import files to database
     *
     * @package     MediaSync
     * @license     http://opensource.org/licenses/gpl-2.0.php GNU Public License
     * @since       0.1.0
     * @author      Erol Živina
     */
    if ( !class_exists( 'MediaSync' ) ) :
    
        class MediaSync
        {
            /**
             * Render main plugin content
             *
             * @since 0.1.0
             * @return void
             */
            static public function media_sync_main_page()
            {
    
                if (!current_user_can('update_plugins')) {
                    wp_die(__('You do not have sufficient permissions to access this page.', 'media-sync'));
                }
    
                $scan_files = isset($_GET['scan_files']) && $_GET['scan_files'] == true;
    
                $here = esc_url(get_admin_url(null, 'upload.php?page=media-sync-page'));
    
                $upload_dir = wp_upload_dir();
                $uploads_dir = str_replace(get_home_path(), DIRECTORY_SEPARATOR, $upload_dir['basedir']);
                ?>
    
                <div class="wrap main-media-sync-page" xmlns="http://www.w3.org/1999/html" xmlns="http://www.w3.org/1999/html">
                    <h1><?= __('Media Sync', 'media-sync') ?></h1>
    
                    <?php if ($scan_files) : ?>
                        <div class="notice notice-error">
                            <p><?= __('Please backup your database! This plugin makes database changes.', 'media-sync') ?></p>
                        </div>
                        <div class="notice notice-success notice-files-imported">
                            <p><?= sprintf(__('Done! Highlighted files were successfully imported. %s to see changes.', 'media-sync'),
                                    '<a href="'.add_query_arg('scan_files', 1, $here).'">'.__('Re-scan', 'media-sync').'</a>') ?></p>
                        </div>
                    <?php endif; ?>
    
                    <div class="media-sync-list-files">
                        <form action="<?= $here ?>" method="POST">
                            <input type="hidden" name="page" value="media-sync-page"/>
                            <div class="media-sync-buttons-holder">
                                <p class="media-sync-button-holder">
                                    <?php if (!$scan_files) : ?>
                                        <a class="button button-primary"
                                           href="<?= add_query_arg('scan_files', 1, $here) ?>"><?= __('Scan Files', 'media-sync') ?></a>
                                    <?php endif; ?>
                                    <?php if ($scan_files) : ?>
                                        <button class="button button-primary js-import-selected"><?= __('Import Selected', 'media-sync') ?></button>
                                        <span class="spinner import-spinner"></span>
    
                                        <span class="media-sync-dry-run-holder">
                                        <input type="checkbox" id="dry-run" name="dry_run" checked="checked" />
                                        <label for="dry-run"><?= __('Dry Run (test without making database changes)', 'media-sync') ?></label>
                                    </span>
                                    <?php endif; ?>
                                </p>
                                <?php if (!$scan_files) : ?>
                                    <p class="media-sync-scan-files-message">
                                        <?= sprintf(__('Click "Scan Files" to see content of upload dir: %s', 'media-sync'),
                                            '<code title="'.$upload_dir['basedir'].'">'.$uploads_dir.'</code>') ?>
                                    </p>
                                <?php endif; ?>
                            </div>
    
                            <?php if ($scan_files) : ?>
                                <p class="media-sync-state-holder">
                                <span class="media-sync-progress-holder">
                                    <span class="media-sync-progress"></span>
                                </span>
                                    <span class="media-sync-state">
                                    <span class="media-sync-state-text">
                                        <?= __('Imported', 'media-sync') ?>
                                    </span>
                                    <span class="media-sync-state-number media-sync-imported-count js-media-sync-imported-count">0</span>
                                    <span class="media-sync-state-text">
                                        <?= __('out of', 'media-sync') ?>
                                    </span>
                                    <span class="media-sync-state-number media-sync-selected-count js-media-sync-selected-count">0</span>
                                    <span class="media-sync-state-text">
                                        <?= __('selected items', 'media-sync') ?>
                                    </span>
                                </span>
                                    <span class="media-sync-state media-sync-state-note">
                                    <?= __('Files already in Media Library will be skipped during import', 'media-sync') ?>
                                </span>
                                </p>
    
                                <?php $tree = self::media_sync_get_list_of_uploads(); ?>
                                <?php if (!empty($tree)) : ?>
                                    <div class="media-sync-table-holder">
                                        <table class="wp-list-table widefat fixed media">
                                            <?php self::media_sync_render_thead_tfoot_row('thead') ?>
                                            <tbody id="the-list">
                                            <?php foreach ($tree as $item) : ?>
                                                <?php self::media_sync_render_row($item) ?>
                                            <?php endforeach; ?>
                                            </tbody>
                                            <?php self::media_sync_render_thead_tfoot_row('tfoot') ?>
                                        </table>
                                        <span class="spinner is-active table-spinner"></span>
                                    </div>
                                <?php else : ?>
                                    <p class="media-sync-no-results">
                                        <?= __('Everything seems fine here, there are no files that are not already in your Media Library.', 'media-sync') ?>
                                    </p>
                                <?php endif; ?>
                            <?php endif; ?>
                        </form>
                    </div>
                </div>
    
                <?php
            }
    
            /**
             * Render table header and footer
             *
             * @since 0.1.0
             * @param $tag string (thead|tfoot)
             * @return void
             */
            static public function media_sync_render_thead_tfoot_row($tag)
            {
                $cb_id = 'cb-select-all-' . ($tag == 'thead' ? '1' : '2');
                ?>
                <<?= $tag ?>>
                <tr>
                    <td class="manage-column check-column check-column-all"<?= $tag == 'thead' ? ' id="cb"':''?>>
                        <label class="screen-reader-text" for="<?= $cb_id ?>"><?= __('Select All', 'media-sync') ?></label>
                        <input id="<?= $cb_id ?>" type="checkbox">
                    </td>
                    <th scope="col" class="manage-column column-title column-primary"<?= $tag == 'thead' ? ' id="title"':''?>>
                        <span><?= __('File', 'media-sync') ?></span>
                    </th>
                </tr>
                </<?= $tag ?>>
                <?php
            }
    
            /**
             * Render table row for each file or directory
             *
             * @since 0.1.0
             * @param $item array
             * @return void
             */
            static public function media_sync_render_row($item)
            {
                $has_file_id = isset($item['file_id']) && $item['file_id'] !== false;
                $url = $has_file_id ? esc_url(add_query_arg(array('post' => $item['file_id'], 'action' => 'edit'), get_admin_url(null, 'post.php'))) : $item['url'];
                $url_attr = $item['is_dir'] !== true ? ' target="_blank"' : '';
                $count_children = count($item['children']);
                $cls = 'media-sync-list-file';
                $cls .= ' is-' . ($item['is_dir'] === true ? 'dir' : 'file');
                $cls .= ' level-' . $item['level'];
                $cls .= ' is-first-level-' . ($item['level'] === 1 ? 'yes' : 'no');
                if ($item['is_dir'] !== true) {
                    $cls .= ' is-in-db-' . ($has_file_id ? 'yes' : 'no');
                } else {
                    $cls .= ' is-empty-' . ($count_children <= 0 ? 'yes' : 'no');
                }
    
                $toggle_arrows = true; // This can be made optional
                if ($toggle_arrows) {
                    $is_link = $item['is_dir'] !== true;
                    $cls .= ' toggle-arrows-yes';
                } else {
                    $is_link = $item['is_dir'] !== true || $count_children > 0;
                    $url_attr .= ' class="js-toggle-row"';
                }
    
                $is_trash = isset($item['file_status']) && $item['file_status'] === 'trash';
    
                $row_id = "media-sync-item-" . $item['alias'];
                ?>
    
                <tr class="<?= $cls ?>" id="<?= $row_id ?>" data-parent-id="media-sync-item-<?= $item['parent_alias'] ?>">
                    <th scope="row" class="check-column">
                        <label class="screen-reader-text" for="cb-select-<?= $item['alias'] ?>"></label>
                        <input type="checkbox" class="js-checkbox" id="cb-select-<?= $item['alias'] ?>"
                               value="<?= $item['absolute_path'] ?>" data-row-id="<?= $row_id ?>">
                    </th>
                    <td class="title column-title has-row-actions column-primary" data-colname="<?= __('File', 'media-sync') ?>">
                        <?php if (!empty($item['parents'])) : ?>
                            <span class="media-sync-parents">
                            <?php foreach ($item['parents'] as $parent_key => $parent) : ?>
                                <?php
                                $parent_cls = 'media-sync-parent';
                                $parent_cls .= ' is-first-' . ($parent_key == 0 ? 'yes' : 'no');
                                $parent_cls .= ' is-last-' . ($parent_key + 1 == count($item['parents']) ? 'yes' : 'no');
                                ?>
                                <span class="<?= $parent_cls ?>"><i></i></span>
                            <?php endforeach; ?>
                            <span class="clearfix"></span>
                        </span>
                        <?php endif; ?>
    
                        <?php if ($toggle_arrows && $item['is_dir'] === true) : ?>
                            <span class="js-toggle-row media-sync-toggle-row dashicons"></span>
                        <?php endif; ?>
    
                        <?= $is_link ? '<a href="' . $url . '"' . $url_attr . '>' : '' ?>
                        <?php if ($item['is_dir'] === true) : ?>
                            <span class="dashicons dashicons-category"></span>
                        <?php endif; ?>
                        <span class="media-sync-file-name">
                        <?= $item['name'] ?>
                    </span>
                        <?= $is_link ? '</a>' : '' ?>
    
                        <?php if ($item['is_dir'] === true) : ?>
                            <span class="media-sync-num-items"><?= sprintf('(%u %s)', $count_children, $count_children == 1 ? __('item', 'media-sync') : __('items', 'media-sync')) ?></span>
                        <?php endif; ?>
    
                        <?php if ($has_file_id) : ?>
                            <span class="media-sync-already-in-db"> - <?= __('Already in', 'media-sync') ?>
                                <a href="<?= $url ?>" class="dashicons dashicons-admin-media" target="_blank"></a>
                                <?= $is_trash ? ' (' . __('In Trash', 'media-sync') . ')' : '' ?>
                            </span>
                        <?php endif; ?>
                    </td>
                </tr>
    
                <?php
                if (!empty($item['children'])) :
                    foreach ($item['children'] as $child_item) :
                        self::media_sync_render_row($child_item);
                    endforeach;
                endif;
            }
    
            /**
             * Ajax action to import selected files
             *
             * @since 0.1.0
             * @return void
             */
            static public function media_sync_import_files()
            {
                if (!current_user_can('update_plugins')) {
                    wp_die(__('You do not have sufficient permissions to access this page.', 'media-sync'));
                }
    
                check_ajax_referer( 'media_sync_import_files', 'security' );
    
                // Get database stuff
                global $wpdb;
    
                $result = array();
    
                if(isset($_POST['media_items']) && !empty($_POST['media_items'])) {
    
                    // Make sure that this file is included, as wp_generate_attachment_metadata() depends on it.
                    require_once( ABSPATH . 'wp-admin/includes/image.php' );
    
                    $files_in_db = self::media_sync_get_files_in_db();
    
                    $dry_run = isset($_POST['dry_run']) && json_decode($_POST['dry_run']) === true;
    
                    foreach ($_POST['media_items'] as $media_item) {
    
                        if(isset($media_item['file']) && !empty($media_item['file'])) {
    
                            $absolute_path = $media_item['file'];
                            $relative_path = str_replace(get_home_path(), DIRECTORY_SEPARATOR, $absolute_path);
    
                            // It's quicker to get all files already in db and check that array, than to do this query for each file
                            // $query = "SELECT COUNT(*) FROM {$wpdb->posts} WHERE guid LIKE '%{$relative_path}'";
                            // $is_in_db = intval($wpdb->get_var($query)) > 0;
    
                            $is_in_db = isset($files_in_db[$relative_path]) && !empty($files_in_db[$relative_path]);
    
                            // Check if file is already in database
                            if(!$is_in_db) {
    
                                if(!$dry_run) {
    
                                    // Import file to database (<code>wp_posts</code> and <code>wp_postmeta</code>)
    
                                    // Check the type of file. We'll use this as the 'post_mime_type'.
                                    $filetype = wp_check_filetype( basename( $absolute_path ), null );
    
                                    // Get the file date.
                                    $post_date = date( 'Y-m-d H:i:s', filemtime( $absolute_path ) );
    
                                    // If for whatever reason not found, use current date.
                                    if(!$post_date) {
                                        $post_date = date( 'Y-m-d H:i:s' );
                                    }
    
                                    // Prepare an array of post data for the attachment.
                                    $attachment = array(
                                        'guid'           => get_site_url() . $relative_path,
                                        'post_mime_type' => $filetype['type'],
                                        'post_title'     => preg_replace( '/\.[^.]+$/', '', basename( $relative_path ) ),
                                        'post_content'   => '',
                                        'post_status'    => 'inherit',
                                        'post_date'      => $post_date
                                    );
    
                                    // Insert the attachment.
                                    $attach_id = wp_insert_attachment( $attachment, $absolute_path );
    
                                    // Generate the metadata for the attachment, and update the database record.
                                    $attach_data = wp_generate_attachment_metadata( $attach_id, $absolute_path );
                                    wp_update_attachment_metadata( $attach_id, $attach_data );
    
                                    $result[] =  array(
                                        'row_id' => $media_item['row_id'],
                                        'inserted' => !!$attach_id
                                    );
                                } else {
                                    $result[] = array(
                                        'row_id' => $media_item['row_id'],
                                        'inserted' => true
                                    );
                                }
                            }
                        }
                    }
                }
    
                echo json_encode($result);
    
                wp_die(); // Must have for Ajax calls
            }
    
            /**
             * Scan "uploads" directory and return recursive list of files and directories
             *
             * @since 0.1.0
             * @return $tree array
             */
            static private function media_sync_get_list_of_uploads()
            {
                $upload_dir = wp_upload_dir();
    
                if(!($upload_dir && $upload_dir['basedir'])) {
                    return array();
                }
    
                return self::media_sync_get_list_of_files($upload_dir['basedir'], $upload_dir['basedir'], self::media_sync_get_files_in_db());
            }
    
            /**
             * Scan directory (passed as first value) and return recursive list of files and directories
             *
             * @since 0.1.0
             * @param $current_dir_path string  Changing recursively for each directory that gets iterated
             * @param $uploads_dir_path string  Main "uploads" directory
             * @param $files_in_db array        List of files that are already in database
             * @return $tree array
             */
            static private function media_sync_get_list_of_files($current_dir_path, $uploads_dir_path, $files_in_db)
            {
                $obj_rdi = new RecursiveDirectoryIterator($current_dir_path);
                $tree = array();
                $i = 0;
    
                foreach ($obj_rdi as $full_path => $file) {
                    // Only file name
                    $file_name = $file->getFilename();
                    // If it contains image size at the end (i.e. -100x100.jpg)
                    $is_thumb = preg_match('/[_-]\d+x\d+(?=\.[a-z]{3,4}$)/im', $file_name) == true;
    
                    if ($obj_rdi->isDot() || $file_name == ".DS_Store" || $file_name == ".htaccess" || $file_name == "index.php" || $is_thumb) {
                        continue;
                    }
    
                    $children = $file->isDir() ? self::media_sync_get_list_of_files($file->getPathname(), $uploads_dir_path, $files_in_db) : array();
    
                    if ($file->isDir() && empty($children)) {
                        continue;
                    }
    
                    $uid_backup = uniqid('', true);
    
                    $parents_path = ltrim(str_replace($uploads_dir_path, '', $current_dir_path), DIRECTORY_SEPARATOR);
                    $parents = !empty($parents_path) ? explode(DIRECTORY_SEPARATOR, $parents_path) : array();
                    $parent_alias = !empty($parents_path) ? sanitize_title(str_replace(DIRECTORY_SEPARATOR, '_', $parents_path), $uid_backup) : '';
                    $alias = sanitize_title($file_name, $uid_backup);
    
                    $item = array(
                        'alias' => (!empty($parent_alias) ? $parent_alias . '_' : '') . $alias,
                        'name' => $file_name,
                        'is_dir' => !!$file->isDir(),
                        'level' => count($parents) + 1,
                        'parent_alias' => $parent_alias,
                        'parents' => $parents,
                        'children' => $children,
                        'absolute_path' => $full_path
                    );
    
                    if ($file->isDir()) {
                        $item['relative_path'] = '';
                        $item['url'] = 'javascript:;';
                    } else {
    
                        $relative_path = str_replace(get_home_path(), DIRECTORY_SEPARATOR, $full_path);
                        $file_in_db = isset($files_in_db[$relative_path]) && !empty($files_in_db[$relative_path]) ?
                            $files_in_db[$relative_path] : false;
    
                        $item['relative_path'] = $relative_path;
                        $item['url'] = get_site_url() . $relative_path;
                        $item['file_id'] = $file_in_db && !empty($file_in_db['id']) ? $file_in_db['id'] : false;
                        $item['file_status'] = $file_in_db && !empty($file_in_db['status']) ? $file_in_db['status'] : false;
                    }
    
                    // Add with this "key" for sorting
                    $tree[$alias . '__' . $i] = $item;
    
                    $i++;
                }
    
                // Sort items by key
                ksort($tree, SORT_NATURAL);
    
                return $tree;
            }
    
            /**
             * Get list of files that are already in database
             *
             * Caching does not seem to work
             *
             * @since 0.1.0
             * @param $cache bool Could be used to skip cache and get new values (only for first import batch for example)
             * @return $files_in_db array
             */
            static private function media_sync_get_files_in_db($cache = true)
            {
                $files_in_db = wp_cache_get('media_sync_get_files_in_db', '', true);
    
                if ($files_in_db === false || $cache === false) {
    
                    $media_query = new WP_Query(array(
                        'post_type' => 'attachment',
                        'post_status' => array('inherit', 'trash'),
                        'posts_per_page' => -1
                    ));
    
                    $files = array();
                    foreach ($media_query->posts as $post) {
                        $files[str_replace(get_site_url(), "", wp_get_attachment_url($post->ID))] = array(
                            'id' => $post->ID,
                            'name' => $post->post_title,
                            'status' => $post->post_status
                        );
                    }
    
                    $files_in_db = $files;
                    wp_cache_set('media_sync_get_files_in_db', $files_in_db, '', 600);
                }
    
                return $files_in_db;
            }
        }
    endif; // End if class_exists check.
    ?>
    Plugin Author erolsk8

    (@erolsk8)

    You’re right @iboone, plugin’s minimal PHP version was set to 5.2.4, but short array syntax was added in PHP 5.4.

    Thank you for provided code, I implemented it and it’s now available in new 0.1.6 version of this plugin.

    Please let me know if it works and we can close this topic.

    Thread Starter iboone

    (@iboone)

    thanks for the quick update.

    it seems to work 🙂

Viewing 4 replies - 1 through 4 (of 4 total)
  • The topic ‘Bug under PHP 5.4’ is closed to new replies.