File "gv-updates.js"

Full path: /home/kosmetik/public_html/wp-content/plugins/gplvault-updater/admin/assets/scripts/gv-updates.js
File size: 16.68 B
MIME-type: text/x-asm
Charset: utf-8

Download   Open   Edit   Advanced Editor   Back

/**
 * Functions for ajaxified updates for GPLVault items
 * @since 4.0.0-beta
 */
/** global pagenow */
window.gplvault = gplvault || {};
(function ($, wp, gplvault, settings) {
  gplvault = gplvault || {};
  var $document = $(document),
    gv = gplvault,
    __ = wp.i18n.__,
    _x = wp.i18n._x,
    sprintf = wp.i18n.sprintf;

  gv.updates = {};
  settings = _.extend(settings, gv.common.settings || {})

  gv.updates.l10n = {
    searchResults: '',
    searchResultsLabel: '',
    noPlugins: '',
    noItemsSelected: '',
    updating: '',
    pluginUpdated: '',
    themeUpdated: '',
    update: '',
    updateNow: '',
    pluginUpdateNowLabel: '',
    updateFailedShort: '',
    updateFailed: '',
    pluginUpdatingLabel: '',
    pluginUpdatedLabel: '',
    pluginUpdateFailedLabel: '',
    updatingMsg: '',
    updatedMsg: '',
    updateCancel: '',
    beforeunload: '',
    unknownError: '',
    connectionError: '',
    nonceError: '',
    pluginsFound: '',
    noPluginsFound: '',
  };

  gv.updates.l10n = window.wp.deprecateL10nObject('gv.updates.l10n', gv.updates.l10n, '5.5.0');

  gv.updates.searchText = '';
  gv.updates.shouldAskFSCreds = false;
  gv.updates.fsCreds = {
    ftp:       {
      host:           '',
      username:       '',
      password:       '',
      connectionType: ''
    },
    ssh:       {
      publicKey:  '',
      privateKey: ''
    },
    fsNonce: '',
    available: false
  };
  gv.updates.ajaxLocked = false;
  gv.updates.adminNotice = wp.template( 'wp-updates-admin-notice' );
  gv.updates.queue = [];

  gv.updates.$elToReturnFocusToFromCredentialsModal = undefined;
  gv.updates.shouldRequestFilesystemCredentials = false;

  gv.updates.addAdminNotice = function(data) {

  };

  gv.updates.ajax = function(context, data) {
    var options = {};

    if (gv.updates.ajaxLocked) {
      gv.updates.queue.push({
        context: context,
        data: data,
      });

      return $.Deferred();
    }

    gv.updates.ajaxLocked = true;
    options.context = context;

    if (data.success) {
      options.success = data.success;
      delete data.success;
    }

    if ( data.error ) {
      options.error = data.error;
      delete data.error;
    }

    options.data = _.extend( data, {
      _fs_nonce:       gv.updates.fsCreds.fsNonce,
      username:        gv.updates.fsCreds.ftp.username,
      password:        gv.updates.fsCreds.ftp.password,
      hostname:        gv.updates.fsCreds.ftp.hostname,
      connection_type: gv.updates.fsCreds.ftp.connectionType,
      public_key:      gv.updates.fsCreds.ssh.publicKey,
      private_key:     gv.updates.fsCreds.ssh.privateKey
    } );

    return gv.common.ajax(options).always(gv.updates.ajaxAlways);
  };

  gv.updates.ajaxAlways = function(response) {
    gv.updates.ajaxLocked = false;
    gv.updates.queueChecker();

    if ( 'undefined' !== typeof response.debug && window.console && window.console.log ) {
      _.map( response.debug, function( message ) {
        // Remove all HTML tags and write a message to the console.
        window.console.log( wp.sanitize.stripTagsAndEncodeText( message ) );
      } );
    }
  };

  /**
   * Validates an Ajax response
   *
   * @param {(Object|string)} response              Response from the server.
   * @param {function=}       response.always       Optional. Callback for when the Deferred is resolved or rejected.
   * @param {string=}         response.statusText   Optional. Status message corresponding to the status code.
   * @param {string=}         response.responseText Optional. Request response as text.
   */
  gv.updates.isValidResponse = function(response) {
    var error = __( 'Something went wrong.', 'gplvault' ),
      errorMessage;

    if (_.isObject(response) && ! _.isFunction(response.always)) {
      return true;
    }

    if ( _.isString( response ) && '-1' === response ) {
      error = __( 'An error has occurred. Please reload the page and try again.' );
    } else if ( _.isString( response ) ) {
      error = response;
    } else if ( 'undefined' !== typeof response.readyState && 0 === response.readyState ) {
      error = __( 'Connection lost or the server is busy. Please try again later.', 'gplvault' );
    } else if ( _.isString( response.responseText ) && '' !== response.responseText ) {
      error = response.responseText;
    } else if ( _.isString( response.statusText ) ) {
      error = response.statusText;
    }

    errorMessage = __( 'Update failed: %s', 'gplvault' );

    error = error.replace( /<[\/a-z][^<>]*>/gi, '' );
    errorMessage = errorMessage.replace( '%s', error );

    gv.updates.addAdminNotice( {
      type:        'error',
      title: __('Update failed.', 'gplvault'),
      message:   _.escape( errorMessage )
    } );

    // Remove the lock, and clear the queue.
    gv.updates.ajaxLocked = false;
    gv.updates.queue      = [];

    // Change buttons of all running updates.
    $( '.button.updating-message' )
      .removeClass( 'updating-message' )
      .removeAttr( 'aria-label' )
      .prop( 'disabled', true )
      .text( __( 'Update failed.', 'gplvault' ) );

    $( '.updating-message:not(.button):not(.thickbox)' )
      .removeClass( 'updating-message notice-warning' )
      .addClass( 'notice-error' )
      .find( 'p' )
      .removeAttr( 'aria-label' )
      .text( errorMessage );

    wp.a11y.speak( errorMessage, 'assertive' );

    return false;
  };

  gv.updates.updatePlugin = function(args) {
    var $updateRow, $message, message, $updateBtn, promise;

    $updateRow = $( 'tr[data-plugin="' + args.plugin + '"]' );

    args = _.extend({
      product_id: $updateRow.data('product'),
      slug: $updateRow.data('slug'),
      // success: gv.updates.updatePluginSuccess,
      // error: gv.updates.updatePluginError,
    }, args);

    $updateBtn = $updateRow.find('.gv-trigger-update').addClass('updating-message');
    $document.trigger( 'gv-plugin-updating', args );

    promise = gv.updates.ajax('update_plugin', args);
    promise.done(gv.updates.updatePluginSuccess).fail(gv.updates.updatePluginError);
    return promise;
  };

  /**
   * Updates the UI appropriately after a successful plugin update.
   *
   * @since 4.0.0-beta
   *
   * @param {Object} response         Ajax server Response
   */
  gv.updates.updatePluginSuccess = function (response) {
    var $updateRow;
    response = response || {};
    response.payload = response.payload || {};

    // here goes gv.updates.decrementCount for type plugin
    $updateRow = $( 'tr[data-plugin="' + response.payload.plugin + '"]' );

    $updateRow.find('.updating-message').remove();
    $updateRow.find(':checkbox').val('');
    $updateRow.addClass('gv-updated');

    wp.a11y.speak( __( 'Update completed successfully.', 'gplvault' ) );
    gv.updates.decrementCount('plugin');

    $document.trigger( 'gv-plugin-update-success', response );
  };

  gv.updates.decrementCount = function (type) {
    settings.totals.counts.total = Math.max( --settings.totals.counts.total, 0 );

    if ( 'plugin' === type ) {
      settings.totals.counts.plugins = Math.max( --settings.totals.counts.plugins, 0 );
    } else if ( 'theme' === type ) {
      settings.totals.counts.themes = Math.max( --settings.totals.counts.themes, 0 );
    }

    gv.updates.refreshCount();
  };

  gv.updates.updatePluginError = function (response) {
    response = response || {};
    response.payload = response.payload || {};
    var $updateRow, $updateTrigger, errorMessage,
      errorTitle = __('Error', 'gplvault');

    if ( ! gv.updates.isValidResponse( response ) ) {
      return;
    }

    if ( gv.updates.maybeHandleCredentialError( response, 'update_plugin' ) ) {
      return;
    }

    errorMessage = sprintf(
      /* translators: %s: Error string for a failed update. */
      __( 'Update failed: %s' ),
      response.payload.errorMessage
    );

    if ('gplvault_plugins' === settings.pagenow) {
      if (response.payload && response.payload.plugin) {
        $updateRow = $('tr[data-plugin="' + response.payload.plugin + '"]');
      } else if (response.payload && response.payload.product_id) {
        $updateRow = $('tr[data-product="' + response.payload.product_id + '"]');
      } else if (response.payload && response.payload.slug) {
        $updateRow = $('tr[data-product="' + response.payload.slug + '"]');
      }

      if ($updateRow && $updateRow.length > 0) {
        $updateTrigger = $updateRow.find('.updating-message');
      } else {
        $updateTrigger = $('button.updating-message:first', '.gv-layout__table');
        $updateRow = $updateTrigger.closest('tr[data-plugin]');
      }

      $updateTrigger.removeClass('updating-message');
      $updateRow.addClass('gv-failed');
      $updateRow.find(':checked').prop('checked', false);
      errorTitle = $updateRow.find('.plugin-title > strong').text();
    }

    gv.common.setPopupOptions({
      life: 3000,
      pool: 4,
    }).add({
      type: 'error',
      title: errorTitle,
      content: errorMessage
    });

    $document.trigger( 'gv-plugin-update-error', response );
  };

  gv.updates.credentialError = function( response, context ) {
    gv.updates.queue.unshift( {
      context: context,

      /*
       * Not cool that we're depending on response for this data.
       * This would feel more whole in a view all tied together.
       */
      data: response
    } );

    gv.updates.filesystemCredentials.available = false;
    gv.updates.showErrorInCredentialsForm( response.message );
    gv.updates.requestFilesystemCredentials();
  };

  gv.updates.maybeRequestFilesystemCredentials = function( event ) {
    if ( gv.updates.shouldRequestFilesystemCredentials && ! gv.updates.ajaxLocked ) {
      gv.updates.requestFilesystemCredentials( event );
    }
  };

  gv.updates.requestFilesystemCredentials = function( event ) {
    if ( false === gv.updates.filesystemCredentials.available ) {
      /*
       * After exiting the credentials request modal,
       * return the focus to the element triggering the request.
       */
      if ( event && ! gv.updates.$elToReturnFocusToFromCredentialsModal ) {
        gv.updates.$elToReturnFocusToFromCredentialsModal = $( event.target );
      }

      gv.updates.ajaxLocked = true;
      gv.updates.requestForCredentialsModalOpen();
    }
  };

  gv.updates.requestForCredentialsModalOpen = function() {
    var $modal = $( '#request-filesystem-credentials-dialog' );

    $( 'body' ).addClass( 'modal-open' );
    $modal.show();
    $modal.find( 'input:enabled:first' ).trigger( 'focus' );
    $modal.on( 'keydown', gv.updates.keydown );
  };

  gv.updates.keydown = function( event ) {
    if ( 27 === event.keyCode ) {
      gv.updates.requestForCredentialsModalCancel();
    } else if ( 9 === event.keyCode ) {

      // #upgrade button must always be the last focus-able element in the dialog.
      if ( 'upgrade' === event.target.id && ! event.shiftKey ) {
        $( '#hostname' ).trigger( 'focus' );

        event.preventDefault();
      } else if ( 'hostname' === event.target.id && event.shiftKey ) {
        $( '#upgrade' ).trigger( 'focus' );

        event.preventDefault();
      }
    }
  };

  gv.updates.requestForCredentialsModalCancel = function() {

    // Not ajaxLocked and no queue means we already have cleared things up.
    if ( ! gv.updates.ajaxLocked && ! gv.updates.queue.length ) {
      return;
    }

    _.each( gv.updates.queue, function( job ) {
      $document.trigger( 'credential-modal-cancel', job );
    } );

    // Remove the lock, and clear the queue.
    gv.updates.ajaxLocked = false;
    gv.updates.queue = [];

    gv.updates.requestForCredentialsModalClose();
  };

  gv.updates.requestForCredentialsModalClose = function() {
    $( '#request-filesystem-credentials-dialog' ).hide();
    $( 'body' ).removeClass( 'modal-open' );

    if ( gv.updates.$elToReturnFocusToFromCredentialsModal ) {
      gv.updates.$elToReturnFocusToFromCredentialsModal.focus();
    }
  };

  gv.updates.showErrorInCredentialsForm = function( message ) {
    var $filesystemForm = $( '#request-filesystem-credentials-form' );

    // Remove any existing error.
    $filesystemForm.find( '.notice' ).remove();
    $filesystemForm.find( '#request-filesystem-credentials-title' ).after( '<div class="notice notice-alt notice-error"><p>' + message + '</p></div>' );
  };

  gv.updates.maybeHandleCredentialError = function (response, context) {
    if ( gv.updates.shouldRequestFilesystemCredentials && response.errorCode && 'unable_to_connect_to_filesystem' === response.errorCode ) {
      gv.updates.credentialError( response, context );
      return true;
    }

    return false;
  };

  gv.updates.beforeunload = function() {
    if ( gv.updates.ajaxLocked ) {
      return __( 'Updates may not complete if you navigate away from this page.', 'gplvault' );
    }
  };

  gv.updates.updateTheme = function(args) {
    $document.trigger('gv-theme-updating');
    return gv.updates.ajax('update_theme', args);
  }

  gv.updates.queueChecker = function() {
    var job;

    if (gv.updates.ajaxLocked || ! gv.updates.queue.length) {
      return;
    }

    job = gv.updates.queue.shift();

    switch(job.context) {
      case 'update_plugin':
        gv.updates.updatePlugin(job.data);
        break;
      case 'update_theme':
        gv.updates.updateTheme(job.data);
        break;
      default:
        break;
    }
  };

  gv.updates.refreshCount = function () {
    var $menuMainItemCount = $('.gv-count-total', '#adminmenuwrap'),
      $menuPluginsCount = $('.gv-count-plugins', '#adminmenuwrap'),
      $menuThemesCount = $('.gv-count-themes', '#adminmenuwrap'),
      itemCount;

    $menuMainItemCount.each( function (index, element) {
      element.className = element.className.replace( /count-\d+/, 'count-' + settings.totals.counts.total );
    } );
    if (settings.totals.counts.total > 0) {
      $menuMainItemCount.find('.update-count').text(settings.totals.counts.total);
    } else {
      $menuMainItemCount.remove();
    }

    $menuPluginsCount.each( function( index, element ) {
      element.className = element.className.replace( /count-\d+/, 'count-' + settings.totals.counts.plugins );
    } );
    if (settings.totals.counts.plugins > 0) {
      $menuPluginsCount.find('.update-count').text(settings.totals.counts.plugins);
    } else {
      $menuPluginsCount.remove();
    }

    $menuThemesCount.each( function( index, element ) {
      element.className = element.className.replace( /count-\d+/, 'count-' + settings.totals.counts.themes );
    } );
    if (settings.totals.counts.themes > 0) {
      $menuThemesCount.find('.update-count').text(settings.totals.counts.themes);
    } else {
      $menuThemesCount.remove();
    }

    if ('gplvault_plugins' === settings.pagenow ) {
      itemCount = settings.totals.counts.plugins;
    } else if ('gplvault_themes' === settings.pagenow) {
      itemCount = settings.totals.counts.themes;
    }

    if (itemCount > 0) {
      $( '.subsubsub .upgrade .count' ).text( '(' + itemCount + ')' );
    } else {
      $( '.subsubsub .upgrade' ).remove();
      $( '.subsubsub li:last' ).html( function() { return $( this ).children(); } );
    }
  };


  $(function () {
    var $bulkPluginsForm = $('#gv_bulk_plugins_form');

    settings = _.extend(settings, window._gvUpdatesItemCounts || {});

    if (settings.totals) {
      gv.updates.refreshCount();
    }

    $bulkPluginsForm.on('change', function (e) {
      var $_instance = $(this),
        formData,
        plugins,
        action,
        $doActionBtn = $_instance.find('#doaction');

      formData = $_instance.serializeObj();
      plugins = formData.gv_bulk_plugins;
      plugins = _.isArray(plugins) ? plugins : (_.isString(plugins) ? [plugins] : []);
      plugins = plugins.filter(Boolean);
      action = formData.action !== '-1';

      if (plugins.length > 0 && action) {
        $doActionBtn.prop('disabled', false);
      } else {
        $doActionBtn.prop('disabled', true);
      }
    });

    $bulkPluginsForm.on('submit', function (e) {
      e.preventDefault();
      var $_form = $(this),
        plugins,
        formData = $_form.serializeObj();

      plugins = formData.gv_bulk_plugins;
      plugins = _.isArray(plugins) ? plugins : (_.isString(plugins) ? [plugins] : []);
      plugins = plugins.filter(Boolean);

      plugins.forEach(function (plugin) {
        var promise = gv.updates.updatePlugin({
          plugin: plugin,
        });
      });
    });

    $bulkPluginsForm.on('click', 'tr.has-update .gv-trigger-update', function (e) {
      var $_instance = $(this),
        $pluginRow = $_instance.parents('tr');

      e.preventDefault();
      if ( $_instance.hasClass( 'updating-message' ) || $_instance.hasClass( 'button-disabled' ) ) {
        return;
      }

      gv.updates.maybeRequestFilesystemCredentials(e);
      gv.updates.updatePlugin({
        plugin: $pluginRow.data( 'plugin' ),
      });
    });
  });
})(jQuery, window.wp, window.gplvault, window._gvUpdatesSettings);