Commit inicial - WordPress Análisis de Precios Unitarios

- WordPress core y plugins
- Tema Twenty Twenty-Four configurado
- Plugin allow-unfiltered-html.php simplificado
- .gitignore configurado para excluir wp-config.php y uploads

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
root
2025-11-03 21:04:30 -06:00
commit a22573bf0b
24068 changed files with 4993111 additions and 0 deletions

View File

@@ -0,0 +1,3 @@
<svg width="10" height="6" viewBox="0 0 10 6" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0.984375 0H9.01562C9.57812 0 9.85938 0.6875 9.45312 1.09375L5.45312 5.09375C5.20312 5.34375 4.79688 5.34375 4.54688 5.09375L0.546875 1.09375C0.140625 0.6875 0.421875 0 0.984375 0Z" fill="#444648"/>
</svg>

After

Width:  |  Height:  |  Size: 309 B

View File

@@ -0,0 +1,3 @@
<svg width="10" height="6" viewBox="0 0 10 6" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9 6H0.96875C0.40625 6 0.125 5.34375 0.53125 4.9375L4.53125 0.9375C4.78125 0.6875 5.1875 0.6875 5.4375 0.9375L9.4375 4.9375C9.84375 5.34375 9.5625 6 9 6Z" fill="#444648"/>
</svg>

After

Width:  |  Height:  |  Size: 282 B

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 154 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,26 @@
const ToolsCollection = require('./tools');
const CategoryModel = require('../models/category');
/**
* Backbone collection for representing a collection of categories.
*/
module.exports = Backbone.Collection.extend( {
model: CategoryModel, // Reference to the CategoryModel
/**
* Parse the response data to create CategoryModel instances.
*
* @param {Object} response The response data.
* @returns {Array} An array of CategoryModel instances.
*/
parse: function( response ) {
// Iterate over each category in the response
return _.map( response, function( tools, categoryName ) {
// Create a CategoryModel for each category
return new CategoryModel( {
name: categoryName,
tools: new ToolsCollection(tools)
} );
} );
}
} );

View File

@@ -0,0 +1,10 @@
/**
* Backbone collection for representing a collection of tools.
*/
module.exports = Backbone.Collection.extend({
// Define the model for the collection
model: require('../models/tool'), // Reference to the Tool model
});

View File

@@ -0,0 +1,314 @@
( function( $ ) {
// Wait for the DOM to be ready
$(document).ready(() => {
// Import necessary modules
const CategoriesCollection = require('./collections/categories');
const SearchView = require('./views/search');
const FilterView = require('./views/filter');
const {
getButtonHtml,
redirectToUri,
updateButtonClassWhileInstalling,
updateButtonClassIfInstallationFailed,
updateButtonClassAfterActivated,
updateButtonClassAfterInstallation,
handleError,
getGetStartedButtonText,
getActivateButtonText,
getInstallNowButtonText
} = require('./helperFunctions');
// Create a new instance of CategoriesCollection
const categoriesCollection = new CategoriesCollection();
// Define the GrowthTools view
const GrowthTools = Backbone.View.extend({
el: '.growth-tools-list',
events: {
'click .tve-action-btn-learn-more': 'redirectToUri',
'click .tve-action-btn-get-started': 'redirectToDashboard',
'click .tve-action-btn-install-now': 'initInstallation',
'click .tve-action-btn-activate': 'activatePlugin',
'click .tool-name': 'redirectToUri'
},
initialize: function() {
// Show loader while fetching data
TVE_Dash.showLoader(true);
const self = this;
categoriesCollection.url = TVD_AM_CONST.baseUrl;
categoriesCollection.fetch({
success: function( collection ) {
if ( collection.length === 0 ) {
// Handle case where no data is returned
self.$el.empty();
self.$el.append( '<div class="growth-tools-not-found"><span>No tools found</span><svg class="td-icon"><use xlink:href="#icon-no-tools-found"></use></svg></div>' );
} else {
// Set fetched data to view properties
self.categories = collection;
self.filteredTools = collection;
// Render the view after setting the collection
self.render();
}
},
error: function( collection, response ) {
// Error handling
TVE_Dash.err( 'Error fetching data:', response, 3000, null, 'top' );
},
complete: function() {
// Hide loader after rendering
TVE_Dash.hideLoader();
}
});
},
filterTools: function() {
// Get selected category and search text
const selectedOption = $( '#tools-category-select option:selected' ).text();
const category = encodeURIComponent( selectedOption );
const search = encodeURIComponent( $( '#tvd-search-growth-tools' ).val().trim().toLowerCase() );
// Show loader while fetching filtered data
TVE_Dash.showLoader( true );
const self = this;
categoriesCollection.url = TVD_AM_CONST.baseUrl + '?category=' + category + '&query=' + search;
categoriesCollection.fetch({
success: function( collection ) {
if ( collection.length === 0 ) {
// Handle case where no data is returned
self.$el.empty();
self.$el.append( '<div class="growth-tools-not-found"><span>No tools found</span><svg class="td-icon"><use xlink:href="#icon-no-tools-found"></use></svg></div>' );
} else {
// Set fetched data to view properties
self.categories = collection;
self.filteredTools = collection;
// Render the view after setting the collection
self.render();
}
},
error: function( collection, response ) {
// Error handling
TVE_Dash.err( 'Error fetching data:', response, 3000, null, 'top' );
},
complete: function() {
// Hide loader after rendering
TVE_Dash.hideLoader();
}
});
},
// Handle redirection to external URL
redirectToUri: function( event ) {
redirectToUri( event, '_blank' );
},
// Handle redirection to dashboard
redirectToDashboard: function( event ) {
redirectToUri( event );
},
// Initialize plugin installation process
initInstallation: function( event ) {
event.preventDefault();
const button = $( event.currentTarget );
const pluginSlug = button.data( 'plugin-slug' );
updateButtonClassWhileInstalling( button );
// Disable the button
button.prop( 'disabled', true ).text( 'Installing...' );
// Ensure plugin slug is available
if ( !pluginSlug ) {
TVE_Dash.err( 'Plugin slug is missing.', 3000, null, 'top' );
button.prop( 'disabled', false ).html( getInstallNowButtonText() );
return;
}
const apiUrl = TVD_AM_CONST.baseUrl;
const data = {
plugin_slug: pluginSlug,
action: 'install'
};
// Define request options
const requestOptions = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify( data ),
};
let self = this;
// Send the POST request using fetch
fetch( apiUrl, requestOptions )
.then( response => {
// Check if request was successful
if ( !response.ok ) {
return handleError( response );
}
return response.json(); // Parse response JSON
})
.then( response_data => {
// If response contains download link, install plugin
if ( response_data && response_data?.dl ) {
self.installPlugin( event );
} else {
// Otherwise, activate the plugin
TVE_Dash.success( response_data?.success, 3000, null, 'top' );
self.activatePlugin( event );
}
})
.catch( error => {
updateButtonClassIfInstallationFailed( button );
// Handle errors
TVE_Dash.err( 'Error: ' + error.message, 3000, null, 'top' );
button.prop( 'disabled', false ).html( getInstallNowButtonText() );
});
},
// Install plugin from remote URL
installPlugin: function( event ) {
const button = $( event.currentTarget );
const pluginSlug = button.data( 'plugin-slug' );
updateButtonClassWhileInstalling( button );
// Disable the button
button.prop( 'disabled', true ).text( 'Installing...' );
const apiUrl = TVD_AM_CONST.baseUrl;
const data = {
plugin_slug: pluginSlug,
action: 'install'
};
// Define request options
const requestOptions = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify( data ),
};
let self = this;
// Send the POST request using fetch
fetch( apiUrl, requestOptions )
.then( response => {
// Check if request was successful
if ( !response.ok ) {
return handleError( response );
}
return response.json();
})
.then( response_data => {
TVE_Dash.success( response_data?.success, 3000, null, 'top' );
updateButtonClassAfterInstallation( button );
button.html( getActivateButtonText() );
self.activatePlugin( event );
})
.catch( error => {
updateButtonClassIfInstallationFailed( button );
// Handle errors
TVE_Dash.err( 'Error: ' + error.message, 3000, null, 'top' );
button.prop( 'disabled', false ).html( getInstallNowButtonText() );
});
},
// Activate plugin
activatePlugin: function( event ) {
event.preventDefault();
const button = $( event.currentTarget );
const pluginSlug = button.data( 'plugin-slug' );
button.prop( 'disabled', true ).text( 'Activating' );
// Ensure plugin slug is available
if ( !pluginSlug ) {
TVE_Dash.err( 'Plugin slug is missing.', 3000, null, 'top' );
button.prop( 'disabled', false ).html( getActivateButtonText() );
return;
}
const apiUrl = TVD_AM_CONST.baseUrl;
const data = {
plugin_slug: pluginSlug,
action: 'activate'
};
// Define request options
const requestOptions = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify( data ),
};
// Send the POST request using fetch
fetch( apiUrl, requestOptions )
.then( response => {
if ( !response.ok ) {
return handleError( response );
}
return response.json(); // Parse response JSON
})
.then( data => {
// Handle successful response
TVE_Dash.success( data?.success, 3000, null, 'top' );
updateButtonClassAfterActivated( button );
button.prop( 'disabled', false ).html( getGetStartedButtonText() ); // Enable the button
})
.catch(error => {
// Handle errors
TVE_Dash.err( 'Error: ' + error.message, 3000, null, 'top' );
button.prop( 'disabled', false ).html( getActivateButtonText() );
});
},
render: function() {
// Empty the element
this.$el.empty();
// Check if categories collection exists
if ( !this.filteredTools || this.filteredTools.length === 0 ) {
return this;
}
const self = this;
// Loop through each category
this.filteredTools.each( function( category ) {
const $categoryItem = $( '<div class="growth-tools-category-item"></div>' );
const $categoryTitle = $( '<span class="category-title">' + category.get( 'name' ) + '</span>' );
$categoryItem.append( $categoryTitle );
// Check if category has tools
const tools = category.get( 'tools' );
if ( tools && tools.length > 0 ) {
const $toolsContainer = $( '<div class="growth-tools-card"></div>' );
// Loop through each tool in the category
tools.forEach( function( tool ) {
const $toolItem = $( '<div class="growth-tools-card-item"></div>' );
const $toolLogo = $( '<div class="growth-tool-logo"><svg class="td-icon"><use xlink:href="#' + tool.get( 'icon' ) + '"></use></svg></div>' );
const $toolContent = $( '<div class="growth-tool-content"><span class="tool-name" data-url="' + encodeURIComponent( tool.get( 'landing_url' ) ) + '">' + tool.get( 'name' ) + '</span><br/><span class="tool-summary">' + tool.get( 'summary' ) + '</span></div>' );
const $toolAction = $( getButtonHtml( tool ) );
$toolItem.append( $toolLogo, $toolContent, $toolAction );
$toolsContainer.append( $toolItem );
});
$categoryItem.append( $toolsContainer );
}
self.$el.append( $categoryItem );
});
return this;
}
});
// Instantiate GrowthTools view and related views
const growthToolsView = new GrowthTools();
const filterView = new FilterView({
growthToolsView: growthToolsView
});
const searchView = new SearchView({
growthToolsView: growthToolsView
});
// Render filter and search views
filterView.render();
searchView.render();
// Render GrowthTools view
growthToolsView.render();
});
} )( jQuery );

View File

@@ -0,0 +1,260 @@
/**
* Get the button text based on the status of the tool.
*
* @param {string} status The status of the tool.
* @returns {string} The button text.
*/
function getButtonText( status ) {
let content;
switch ( status ) {
case "Activated":
content = getGetStartedButtonText();
break;
case "Installed":
content = getActivateButtonText();
break;
case "Not installed":
content = getInstallNowButtonText();
break;
default:
content = getLearnMoreButtonText();
}
return content;
}
function getLearnMoreButtonText() {
return '<span>Learn More</span>';
}
function getInstallNowButtonText() {
return '<span>Install Now</span>';
}
function getActivateButtonText() {
return '<span>Activate</span>';
}
function getGetStartedButtonText() {
return '<span>Get Started</span>';
}
/**
* Get the action class for the button based on the status of the tool.
*
* @param {string} status The status of the tool.
* @returns {string} The action class for the button.
*/
function getActionClass( status ) {
let className;
switch ( status ) {
case "Activated":
className = 'tve-action-btn-get-started';
break;
case "Installed":
className = 'tve-action-btn-activate';
break;
case "Not installed":
className = 'tve-action-btn-install-now';
break;
default:
className = 'tve-action-btn-learn-more';
}
return className;
}
/**
* Get the button class based on the status of the tool.
*
* @param {string} status The status of the tool.
* @returns {string} The button class.
*/
function getButtonClass( status ) {
let className;
switch ( status ) {
case "Activated":
//Get Started
className = 'tve-btn-get-started';
break;
case "Installed":
//Activate
className = 'tve-btn-action-activate';
break;
case "Not installed":
//Activate
className = 'tve-btn-install-now';
break;
default:
//install Now or Learn More
className = 'tve-btn-learn-more';
}
return className;
}
/**
* Get the button URI based on the status of the tool.
*
* @param {string} status The status of the tool.
* @param {object} tool The tool object.
* @returns {string} The encoded URI for the button.
*/
function getButtonUri( status, tool ) {
let url;
switch ( status ) {
case "Learn More":
url = tool.get( 'landing_url' );
break;
default:
url = tool.get( 'dashboard_uri' );
}
return encodeURIComponent( url );
}
/**
* Get the HTML for the button based on the tool object.
*
* @param {object} tool The tool object.
* @returns {string} The HTML for the button.
*/
function getButtonHtml( tool ) {
let status = tool.get( 'status' );
let pluginSlug = tool.get( 'plugin_slug' );
const uriData = getButtonUri( status, tool )
return '<div class="growth-tool-action"><button class="tve-btn ' + getButtonClass( status ) + ' ' + getActionClass( status ) + '" data-url="' + uriData + '" data-plugin-slug="' + pluginSlug + '">' + getButtonText( status ) + '</button></div>';
}
/**
* Redirect to the URI specified in the event target's dataset.
*
* @param {Event} event The click event.
* @param {string} target The target window or tab to open the URI.
*/
function redirectToUri( event, target = '_self' ) {
const { target: eventTarget } = event || {};
let element = eventTarget;
while ( element ) {
const { dataset } = element;
if ( dataset && dataset.url ) {
const path = decodeURIComponent( dataset.url );
window.open( path, target );
return;
}
// Move up to the parent element
element = element.parentElement;
}
return false;
}
function updateButtonClassWhileInstalling ( button ) {
// Remove previous classes
if ( button.hasClass('tve-action-btn-install-now') ) {
button.removeClass('tve-action-btn-install-now');
}
// Remove install now design
if ( button.hasClass('tve-btn-info') ) {
button.removeClass('tve-btn-info');
}
// Add new class
if ( !button.hasClass('tve-btn-action-installing') ) {
button.addClass('tve-btn-action-installing');
}
}
function updateButtonClassIfInstallationFailed( button ) {
// Remove previous classes
if ( button.hasClass('tve-btn-action-installing') ) {
button.removeClass('tve-btn-action-installing');
}
// Add new class
if ( !button.hasClass('tve-btn-info') ) {
button.addClass('tve-btn-info');
}
if ( !button.hasClass('tve-action-btn-install-now') ) {
button.addClass('tve-action-btn-install-now');
}
}
/**
* Update the button class after installation.
*
* @param {jQuery} button The button element.
*/
function updateButtonClassAfterInstallation( button ) {
// Remove previous classes
if ( button.hasClass( 'tve-action-btn-install-now' ) ) {
button.removeClass( 'tve-action-btn-install-now' );
}
if ( button.hasClass( 'tve-btn-action-installing' ) ) {
button.removeClass( 'tve-btn-action-installing' );
}
// Add new class
if ( !button.hasClass('tve-btn-action-activating') ) {
button.addClass( 'tve-btn-action-activating' );
}
if ( !button.hasClass( 'tve-btn-action-activating' ) ) {
button.addClass( 'tve-btn-action-activating' );
}
}
/**
* Update the button class after activation.
*
* @param {jQuery} button The button element.
*/
function updateButtonClassAfterActivated( button ) {
// Remove previous classes
if ( button.hasClass( 'tve-btn-info' ) ) {
button.removeClass( 'tve-btn-info' );
}
if ( button.hasClass( 'tve-action-btn-activate' ) ) {
button.removeClass( 'tve-action-btn-activate' );
}
// Add new classes
if ( !button.hasClass( 'tve-btn-get-started' ) ) {
button.addClass( 'tve-btn-get-started' );
}
if ( !button.hasClass( 'tve-action-btn-get-started' ) ) {
button.addClass( 'tve-action-btn-get-started' );
}
}
/**
* Handles errors returned from a fetch response.
* Parses JSON response and rejects promise with error message.
*
* @param {Response} response The fetch response object.
* @returns {Promise} A promise rejected with the error message.
*/
function handleError( response ) {
return response.json().then( errorData => {
return Promise.reject( new Error( errorData.message ) );
});
}
// Export the functions to make them accessible from other files
export {
getButtonText,
getActionClass,
getButtonClass,
getButtonHtml,
redirectToUri,
updateButtonClassWhileInstalling,
updateButtonClassIfInstallationFailed,
updateButtonClassAfterInstallation,
updateButtonClassAfterActivated,
handleError,
getGetStartedButtonText,
getActivateButtonText,
getLearnMoreButtonText,
getInstallNowButtonText
};

View File

@@ -0,0 +1,11 @@
const ToolsCollection = require('../collections/tools');
/**
* Backbone model representing a tool.
*/
module.exports = Backbone.Model.extend({
defaults: {
name: '', // Default name of the tool
tools: new ToolsCollection() // Collection of tools
}
});

View File

@@ -0,0 +1,14 @@
/**
* Backbone model for representing a tool.
*/
module.exports = Backbone.Model.extend({
// Default attributes for the tool
defaults: {
name: '', // Name of the tool
path: '', // Path of the tool
icon: '', // Icon representing the tool
status: '', // Status of the tool
summary: '', // Summary or description of the tool
landing_url: '' //url of landing page of the tool
}
});

View File

@@ -0,0 +1,47 @@
/**
* Backbone view for rendering and managing the tools category select dropdown.
*/
( function ( $ ) {
module.exports = Backbone.View.extend( {
// Template for the select dropdown
template: _.template( '<select id="tools-category-select" class="tools-category-select"></select>' ),
// Element to which the view is bound
el: '.tvd-filter-tools',
// DOM events handled by the view
events: {
'change #tools-category-select': 'filterTools' // Change event for category selection
},
/**
* Initialize the view.
* @param {object} options - Options for the view.
* @param {object} options.growthToolsView - Reference to the growth tools view.
*/
initialize: function ( options ) {
this.toolsCategory = JSON.parse( TVD_AM_CONST.tools_category ); // Parse tools category JSON
this.growthToolsView = options.growthToolsView; // Reference to the growth tools view
this.render(); // Render the view
},
// Filter tools based on the selected category
filterTools: function () {
this.growthToolsView.filterTools(); // Call the filterTools method of the growth tools view
},
// Render the view
render: function () {
var $select = $( this.template() ); // Create a select element using the template
$select.append( '<option value="">All Tools</option>' ); // Add default "All Tools" option
_.each( this.toolsCategory, function ( category ) {
$select.append( '<option value="' + category + '">' + category + '</option>' ); // Add options for each category
} );
this.$el.html( $select ); // Add the select element to the view's element
this.$( '#tools-category-select' ).select2( {
minimumResultsForSearch: Infinity
} ); // Initialize select2 plugin for the dropdown
return this; // Return the view instance for chaining
}
} );
} )( jQuery );

View File

@@ -0,0 +1,87 @@
( function( $ ) {
/**
* Backbone view for the growth tools search.
*/
module.exports = Backbone.View.extend( {
// Template for the search input
template: _.template( '<input type="search" id="tvd-search-growth-tools" name="tvd-search" placeholder="Search"><button type="button" class="tvd-tools-search-icon" aria-label="Search"><svg class="td-icon"><use xlink:href="#icon-tvd-search"></use></svg></button><button type="button" class="tvd-clear-search-icon" aria-label="Clear" style="display: none;"><svg class="td-icon"><use xlink:href="#icon-tvd-cross"></use></svg></button>' ),
// Element where the view will be rendered
el: '.tvd-search-elem',
// Events handled by the view
events: {
'click .tvd-clear-search-icon': 'clearSearch',
'keyup #tvd-search-growth-tools': 'handleSearchKeyPress',
'input #tvd-search-growth-tools': 'toggleClearIcon'
},
/**
* Initialize the view.
*
* @param {Object} options Options for the view.
*/
initialize(options) {
this.growthToolsView = options.growthToolsView;
},
/**
* Handle search button click.
*/
searchTools: function() {
this.growthToolsView.filterTools();
},
/**
* Handle clear search button click.
*/
clearSearch: function() {
// Clear the search input
$( '#tvd-search-growth-tools' ).val('');
// Call the API to fetch data
this.growthToolsView.filterTools();
// Hide the clear icon
$( '.tvd-clear-search-icon' ).hide();
// Show the search icon
$( '.tvd-tools-search-icon' ).show();
},
/**
* Handle key press event for search input.
*
* @param {Event} event The keyup event.
*/
handleSearchKeyPress: function(event) {
if ( event.keyCode === 13 ) { // Enter key code
this.growthToolsView.filterTools();
}
},
/**
* Toggle the visibility of the clear icon based on input value.
*/
toggleClearIcon: function() {
let inputVal = $( '#tvd-search-growth-tools' ).val();
if ( inputVal.trim().length > 0 ) {
// Hide the search icon
$( '.tvd-tools-search-icon' ).hide();
// Show the clear icon
$( '.tvd-clear-search-icon' ).show();
} else {
// Hide the clear icon
$( '.tvd-clear-search-icon' ).hide();
// Show the search icon
$( '.tvd-tools-search-icon' ).show();
}
},
/**
* Render the view.
*
* @returns {Object} The rendered view element.
*/
render() {
this.$el.html( this.template() );
return this.$el;
},
} );
} )( jQuery );

View File

@@ -0,0 +1,86 @@
<?php
/**
* Controller for managing growth tools via REST API.
*/
if ( ! class_exists( 'Growth_Tools_Controller' ) ) {
require_once 'Tve_Dash_Growth_Tools.php';
require_once 'Plugin_Installation_Activation_Handler.php';
class Growth_Tools_Controller extends Tve_Dash_Growth_Tools {
/**
* Registers REST routes for growth tools.
*/
public function register_routes() {
register_rest_route( static::REST_NAMESPACE, static::REST_ROUTE, array(
array(
'methods' => WP_REST_Server::READABLE,
'callback' => array( $this, 'get_tools_list' ),
'permission_callback' => '__return_true',
'args' => array(
'category' => array(
'type' => 'string',
'required' => false,
),
'query' => array(
'type' => 'string',
'required' => false,
),
),
),
array(
'methods' => WP_REST_Server::CREATABLE,
'callback' => array( $this, 'maybe_install_activate_plugin' ),
'permission_callback' => '__return_true',
'args' => array(
'plugin_slug' => array(
'type' => 'string',
'required' => true,
),
'action' => array(
'type' => 'string',
'required' => true,
),
),
),
) );
}
/**
* Retrieves a list of growth tools.
*
* @param WP_REST_Request $request The request object.
*
* @return WP_REST_Response Response object containing the list of growth tools.
*/
public function get_tools_list( $request ) {
$filter_category = sanitize_text_field( $request->get_param( 'category' ) );
$search_query = sanitize_text_field( $request->get_param( 'query' ) );
$tools = [];
if ( ! class_exists('Tve_Dash_Growth_Tools') ) {
require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . "Tve_Dash_Growth_Tools.php";
}
$tools_class = Tve_Dash_Growth_Tools::instance();
$tools = $tools_class->filter_tools_by_category_query( $filter_category, $search_query );
return new WP_REST_Response( $tools );
}
/**
* Installs or activates a plugin based on the request.
*
* @param WP_REST_Request $request The request object.
*
* @return WP_REST_Response Response object containing the installation or activation status.
*/
public function maybe_install_activate_plugin( $request ) {
$plugin_slug = sanitize_text_field( $request->get_param( 'plugin_slug' ) );
$action = sanitize_text_field( $request->get_param( 'action' ) );
$installer = new Plugin_Installation_Activation_Handler( $this->tools, $plugin_slug, $action );
return $installer->handle();
}
}
}

View File

@@ -0,0 +1,360 @@
<?php
/**
* Plugin Installation and Activation Handler
*
* Handles the installation and activation of plugins based on different actions.
*
* @package Your_Plugin
* @subpackage Installation_Activation
*/
if (!defined('ABSPATH')) {
exit; // Silence is golden!
}
if (!function_exists('wp_install_plugin')) {
require_once ABSPATH . 'wp-admin/includes/plugin.php';
}
require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
if (!function_exists('WP_Filesystem')) {
require_once ABSPATH . 'wp-admin/includes/file.php';
}
require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'TD_Plugin_Installer_Skin.php';
require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'Thrive_Product_Tags_Helper.php';
class Plugin_Installation_Activation_Handler extends Thrive_Product_Tags_Helper
{
/**
* @var array $tools An array of available tools.
*/
protected $tools;
/**
* @var string $plugin_slug The slug of the plugin.
*/
protected $plugin_slug;
/**
* @var string $action The action to be performed.
*/
protected $action;
/**
* @var object|null $plugin_info Information about the plugin.
*/
protected $plugin_info;
/**
* Constructor.
*
* @param array $tools An array of available tools.
* @param string $slug The slug of the plugin.
* @param string $action The action to be performed.
*/
public function __construct( $tools, $slug, $action ) {
$this->tools = $tools;
$this->plugin_slug = $slug;
$this->action = $action;
$this->plugin_info = $this->get_tool_info_by_slug();
}
/**
* Handles the plugin installation and activation based on the provided action.
*
* @return WP_REST_Response The response object.
*/
public function handle() {
$url = get_option( 'install_remote_url' . $this->plugin_slug, '' );
if ( 'install' === $this->action && ! empty( $url ) ) {
return $this->install_from_url( $url );
}
if ( $this->plugin_info->available_at_org ) {
return $this->handle_product_from_org();
} else {
return $this->handle_thrive_product();
}
}
/**
* Handles the product installation and activation from the WP Org.
*
* @return WP_REST_Response The response object.
*/
private function handle_product_from_org() {
if ( 'install' === $this->action ) {
return $this->install_tools_from_org();
} else {
return $this->activate_tool_using_path();
}
}
/**
* Handles the product installation and activation from Thrive Website.
*
* @return WP_REST_Response The response object.
*/
private function handle_thrive_product()
{
$tag = $this->get_tag_by_slug($this->plugin_slug);
if (empty($tag))
{
return new \WP_REST_Response(
array(
'message' => 'Invalid plugin submitted to install or activate',
),
500
);
}
if ( !TPM_License_Checker_And_Activation_Helper::is_product_purchased( $tag ) ) {
return new \WP_REST_Response(
array(
'message' => 'You need to purchase first to install or activate this plugin',
),
500
);
}
if ( 'install' === $this->action ) {
return $this->install_thrive_product();
} else {
return $this->activate_tool_using_path();
}
}
/**
* Installs plugin from the organization.
*
* @return WP_REST_Response The response object.
*/
public function install_tools_from_org() {
$plugin_slug = $this->plugin_slug;
// Check if the plugin is already installed
if ( is_plugin_inactive( $plugin_slug ) ) {
// Get plugin information from WordPress.org
$api = plugins_api(
'plugin_information',
array(
'slug' => $plugin_slug,
'fields' => array(
'sections' => false,
),
)
);
if ( is_wp_error( $api ) ) {
return $api->get_error_message();
}
$url = get_option( 'install_remote_url' . $this->plugin_slug, '' );
if ( ! empty( $url ) ) {
update_option( 'install_remote_url' . $this->plugin_slug, $api->download_link );
} else {
add_option( 'install_remote_url' . $this->plugin_slug, $api->download_link );
}
return new \WP_REST_Response(
array(
'dl' => true,
'success' => 'Plugin download link restored successfully',
),
200
);
} else {
return new \WP_REST_Response(
array(
'message' => 'Plugin is already installed.',
),
500
);
}
}
/**
* Installs a plugin from a provided URL.
*
* @param string $url The URL of the plugin.
* @return WP_REST_Response The response object.
*/
public function install_from_url( $url ) {
// Install the plugin
$upgrader = new \Plugin_Upgrader( new TD_Plugin_Installer_Skin() );
$install_result = $upgrader->install( $url );
delete_option( 'install_remote_url' . $this->plugin_slug );
if ( $install_result === true || is_wp_error( $install_result ) ) {
return new \WP_REST_Response(
array(
'success' => 'Plugin installed successfully',
),
200
);
} else {
return new \WP_REST_Response(
array(
'message' => 'Something went wrong during installation, please try later!',
),
500
);
}
}
/**
* Activates a plugin using its path.
*
* @return WP_REST_Response The response object.
*/
public function activate_tool_using_path()
{
if ( is_plugin_active( $this->plugin_slug ) ) {
// Plugin is already activated, return a 400 Bad Request response
return new \WP_REST_Response(
array(
'message' => 'Plugin is already activated',
),
400
);
}
// Attempt to activate the plugin
activate_plugin( $this->plugin_info->path );
// Check if the plugin is now active
if ( is_plugin_active( $this->plugin_info->path ) ) {
//If TPM is installed, check and activate license
if( is_TPM_installed() ) {
require_once 'TPM_License_Checker_And_Activation_Helper.php';
$this->activate_thrive_product_license();
}
// Plugin activated successfully, return a 200 OK response
return new \WP_REST_Response(
array(
'message' => 'Plugin activated successfully',
),
200
);
} else {
// Activation failed, return a 500 Internal Server Error response
return new \WP_REST_Response(
array(
'message' => 'Something went wrong during activation, please try later!',
),
500
);
}
}
/**
* Activates the Thrive product license if available.
*
* @return void
*/
private function activate_thrive_product_license() {
if( $tag = $this->get_tag_by_slug( $this->plugin_slug ) ) {
TPM_License_Checker_And_Activation_Helper::activate_license_using_slug( $tag );
}
}
/**
* Get the installation url for a Thrive product.
*
* @return WP_REST_Response The response object.
*/
public function install_thrive_product() {
$download_link = $this->_get_download_url();
if ( is_wp_error( $download_link ) ) {
return $download_link;
}
$url = get_option( 'install_remote_url' . $this->plugin_slug, '' );
if ( ! empty( $url ) ) {
update_option( 'install_remote_url' . $this->plugin_slug, $download_link );
} else {
add_option( 'install_remote_url' . $this->plugin_slug, $download_link );
}
return new \WP_REST_Response(
array(
'dl' => true,
'success' => 'Plugin download link restored successfully',
),
200
);
}
/**
* Retrieves tool information by slug.
*
* @return object|null The tool information or null if not found.
*/
protected function get_tool_info_by_slug() {
foreach ( $this->tools as $plugins ) {
foreach ( $plugins as $plugin ) {
if ( isset( $plugin['plugin_slug'] ) && $plugin['plugin_slug'] === $this->plugin_slug ) {
return (object) $plugin;
}
}
}
return null;
}
/**
* Retrieves the download URL for the thrive plugin.
*
* @return mixed The download URL or WP_Error object.
*/
protected function _get_download_url() {
$options = array(
'timeout' => 20, // seconds
'sslverify' => false,
'headers' => array(
'Accept' => 'application/json',
),
);
/**
* Prepare the POST parameters
*/
$options['body'] = array(
'api_slug' => $this->plugin_slug,
);
$service_api = defined( 'TD_SERVICE_API_URL' ) ? TD_SERVICE_API_URL : 'https://service-api.thrivethemes.com';
$endpoint = rtrim($service_api, '/') . '/plugin/update';
$url = add_query_arg( array( 'p' => $this->_get_hash( $options['body'] ) ), $endpoint );
$result = wp_remote_post( $url, $options );
if ( ! is_wp_error( $result ) ) {
$info = json_decode( wp_remote_retrieve_body( $result ), true );
if ( ! empty( $info ) ) {
return $info['download_url'];
}
}
return new \WP_Error( '400', wp_remote_retrieve_body( $result ) );
}
/**
* Generates a hash based on the provided data.
*
* @param array $data The data to be hashed.
* @return string The generated hash.
*/
protected function _get_hash( $data ) {
$key = '@#$()%*%$^&*(#@$%@#$%93827456MASDFJIK3245';
return md5( $key . serialize( $data ) . $key );
}
}

View File

@@ -0,0 +1,41 @@
<?php
if (!defined('ABSPATH')) {
exit; // Silence is golden!
}
class TD_Plugin_Installer_Skin extends \Plugin_Installer_Skin
{
public $done_header = true;
public $done_footer = true;
public $messages = [];
/**
* Request filesystem credentials.
*
* @param bool $error Whether the request is due to an authentication error.
* @param bool $context The context for the request.
* @param bool $allow_relaxed_file_ownership Whether to allow relaxed file ownership.
*
* @return array The filesystem credentials.
*/
public function request_filesystem_credentials($error = false, $context = false, $allow_relaxed_file_ownership = false)
{
return $this->options;
}
/**
* Provide feedback.
*
* @param string $string The feedback message.
* @param mixed ...$args Additional arguments.
*
* @return void
*/
public function feedback($string, ...$args)
{
if (empty($string)) {
return;
}
$this->messages[] = $string;
}
}

View File

@@ -0,0 +1,90 @@
<?php
/**
* Class TPM_License_Checker_And_Activation_Helper
*
* Responsible for checking if a product is purchased and activating licenses.
*/
if (!class_exists('TPM_License_Checker_And_Activation_Helper')) {
class TPM_License_Checker_And_Activation_Helper extends \TPM_License_Manager
{
/**
* Checks if a product tag exists in any of the licenses.
*
* @param string $product_tag The product tag to search for.
* @return bool True if the product tag exists in any of the licenses, false otherwise.
*/
public static function is_product_purchased( $product_tag )
{
// Get an instance of the TPM_License_Manager class
$TPM_license_manager = self::get_instance();
// Get TTW licenses
$ttw_licenses = $TPM_license_manager->_get_ttw_licenses();
// Check if the product tag exists in any of the licenses
foreach ( $ttw_licenses as $data ) {
if ( self::has_product_tag( $data, $product_tag ) ) {
return true;
}
}
return false;
}
/**
* Checks if a product tag exists in a specific license data.
*
* @param array $license_data The data of a license to check.
* @param string $product_tag The product tag to search for.
* @return bool True if the product tag exists in the license data, false otherwise.
*/
private static function has_product_tag( $license_data, $product_tag )
{
if ( isset( $license_data[ 'tags' ] ) && is_array( $license_data[ 'tags' ] ) ) {
return in_array( 'all', $license_data[ 'tags' ], false ) || in_array( $product_tag, $license_data[ 'tags' ], false );
}
return false;
}
/**
* Activate license using plugin slug.
*
* @param string $plugin_tag The slug of the plugin to activate the license for.
* @return bool True if license activation is successful, false otherwise.
*/
public static function activate_license_using_slug( $plugin_tag ) {
// Get the product list instance
$productList = \TPM_Product_List::get_instance();
// Get the product instance using plugin slug
$product = $productList->get_product_instance( $plugin_tag );
// Activate the license
$product->activate();
// Check if activation is successful
$activationOk = false;
if ( $product->is_licensed() ) {
// If the product is licensed, activation is successful
$activationOk = true;
} else {
// If the product is not licensed, try searching for the license and activate
$product->search_license();
$licensedProducts = \TPM_License_Manager::get_instance()->activate_licenses( array( $product ) );
if ( ! empty( $licensedProducts ) ) {
// If any products are successfully licensed, set activation to true
$activationOk = true;
}
}
// Clear caches after activation
$productList->clear_cache();
\TPM_License_Manager::get_instance()->clear_cache();
// Return the activation status
return $activationOk;
}
}
}

View File

@@ -0,0 +1,42 @@
<?php
/**
* Helper class for managing Thrive product tags.
*/
class Thrive_Product_Tags_Helper {
/**
* Retrieve the product tag by slug.
*
* @param string $slug The slug of the product.
* @return string The corresponding product tag or an empty string if not found.
*/
public static function get_tag_by_slug( $slug ) {
$products = self::thrive_product_tags();
// Return the product tag corresponding to the slug, or an empty string if not found
return $products[ $slug ] ?? '';
}
/**
* Retrieve the array of Thrive product tags.
*
* @return array The array of Thrive product tags with slugs as keys and tags as values.
*/
public static function thrive_product_tags() {
// Define the array of Thrive product tags with slugs as keys and tags as values
return [
'thrive_leads' => 'tl',
'thrive_ultimatum' => 'tu',
'thrive_ovation' => 'tvo',
'thrive_quiz_builder' => 'tqb',
'thrive_apprentice' => 'tva',
'thrive_architect' => 'tcb',
'thrive_comments' => 'tcm',
'thrive_optimize' => 'tab',
'thrive_automator' => 'tap',
'thrive_theme_builder' => 'ttb',
];
}
}

View File

@@ -0,0 +1,244 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
require_once 'Tve_Dash_Growth_Tools_Config.php';
if ( ! class_exists( 'Tve_Dash_Growth_Tools' ) ) {
/**
* Class Tve_Dash_Growth_Tools
*/
class Tve_Dash_Growth_Tools extends Tve_Dash_Growth_Tools_Config {
protected $namespace = 'tve-dash/v1';
/**
* Instance of the class.
*
* @var null
*/
protected static $instance = null;
/**
* Categories.
*
* @var array
*/
protected $categories = [];
/**
* Tools.
*
* @var array
*/
protected $tools = [];
/**
* Data.
*
* @var array
*/
protected $data = [];
/**
* View path.
*
* @var string
*/
protected $view_path = '';
/**
* Get an instance of the class.
*
* @return Tve_Dash_Growth_Tools|null The instance of the class, or null if not instantiated yet.
*/
public static function instance() {
if ( static::$instance === null ) {
static::$instance = new Tve_Dash_Growth_Tools();
}
return static::$instance;
}
/**
* Constructor.
*/
public function __construct() {
if ( is_TPM_installed() ) {
require_once 'TPM_License_Checker_And_Activation_Helper.php';
}
$this->view_path = dirname( dirname( __FILE__ ) ) . DIRECTORY_SEPARATOR . 'templates' . DIRECTORY_SEPARATOR;
$this->categories = $this->categories();
$this->tools = $this->get_tools_order_by_category();
$this->load_dependencies();
$this->get_tools_states( $this->tools );
}
/**
* Dashboard.
*/
public function dashboard() {
$this->enqueue();
$this->render( 'dashboard' );
}
/**
* Get tools states.
*
* @param array $tools_list Tools list.
*/
private function get_tools_states( $tools_list ) {
foreach ( $this->categories as $category ) {
$tools = $tools_list[ $category ];
foreach ( $tools as $key => $tool ) {
$tools[ $key ]['status'] = $this->get_state( $tool['path'] );
// Maybe pro or thrive product
if ( $this->maybe_pro_or_thrive_product( $tools[ $key ] ) ) {
if ( is_TPM_installed() ) {
// Product is purchased user can install
if ( TPM_License_Checker_And_Activation_Helper::is_product_purchased( $tool['plugin_slug'] ) ) {
$tools[ $key ]['status'] = 'Not installed';
} else {
$tools[ $key ]['status'] = 'Learn More';
}
} else {
$tools[ $key ]['status'] = 'Learn More';
}
}
}
$tools_list[ $category ] = $tools;
}
$this->tools = $tools_list;
}
/**
* Check if the given tool is a Pro or Thrive Product.
*
* This function determines whether the provided tool is a Pro or Thrive Product based on its status and availability.
*
* @param array $tool The tool data containing information about the tool.
* Should include at least 'path', 'status', and 'available_at_org' keys.
* @return bool True if the tool is a Pro or Thrive Product, false otherwise.
*/
private function maybe_pro_or_thrive_product( $tool ) {
// If the tool path is empty, it cannot be a Pro or Thrive Product.
if ( empty( $tool['path'] ) ) {
return false;
}
// If the tool status is neither 'Installed' nor 'Activated' and it's not available at the organization, it may be a Pro or Thrive Product.
if ( ! in_array( $tool['status'], [ 'Installed', 'Activated' ], true ) && ! $tool['available_at_org'] ) {
return true;
}
// If the above conditions are not met, the tool is not considered a Pro or Thrive Product.
return false;
}
/**
* Get the state of a plugin.
*
* @param string $plugin_file The path to the main plugin file.
* @return string The state of the plugin.
*/
private function get_state( $plugin_file ) {
// If the plugin file path is empty, return 'Learn More'.
if ( empty( $plugin_file ) ) {
return 'Learn More';
}
// Check if the plugin is active.
if ( is_plugin_active( $plugin_file ) ) {
return 'Activated';
}
// Check if the plugin file exists.
if ( file_exists( WP_PLUGIN_DIR . DIRECTORY_SEPARATOR . $plugin_file ) ) {
return 'Installed';
}
// If the plugin is neither active nor inactive, return 'Not installed'.
return 'Not installed';
}
/**
* Filter tools by category.
*
* @param string $category The category name to filter.
* @param array $categories The array of categories with tools.
* @return array The filtered array of categories with tools.
*/
protected function filter_tools_by_category( $category, $tools_by_categories ) {
// If no specific category is provided, return all categories
if ( empty( $category ) || 'All Tools' === $category ) {
return $tools_by_categories;
}
// Filter categories based on the provided category name
foreach ( $tools_by_categories as $cat => $tools ) {
if ( $category === $cat ) {
return array(
$category => $tools,
);
}
}
// Return an empty array if no matching category is found
return [];
}
public function filter_tools_by_category_query( $filter_category, $search_query ) {
$tools = $this->filter_tools_by_category( $filter_category, $this->tools );
$this->filter_tools_by_query($tools, $search_query );
return $tools;
}
/**
* Filter tools by search query.
*
* @param array $tools The array of tools.
* @param string $searchText The search text.
*/
protected function filter_tools_by_query( &$tools, $searchText ) {
// Convert search text to lowercase for case-insensitive search
$searchTextLower = strtolower( $searchText );
if ( empty( $searchTextLower ) ) {
return ;
}
// Filter array tools
foreach ( $tools as $cat_key => &$category ) {
// Ensure category is represented as an array
$category = is_array( $category ) ? $category : [ $category ];
// Filter category's tools
$category = array_filter( $category, function ( $tool ) use ( $searchTextLower ) {
// Convert tool values to lowercase for case-insensitive search
$nameLower = strtolower( $tool['name'] );
$summaryLower = strtolower( $tool['summary'] );
// Check if any of the tool's values contain the search text
return strpos( $nameLower, $searchTextLower ) !== false || strpos( $summaryLower, $searchTextLower ) !== false;
} );
// Re-index the array to start from zero
$category = array_values( $category );
// Remove category if it has no matching tools
if ( empty( $category ) ) {
unset( $tools[ $cat_key ] );
}
}
}
}
}

View File

@@ -0,0 +1,540 @@
<?php
/**
* Thrive Themes - https://thrivethemes.com
*
* @package thrive-dashboard
*/
if (!defined('ABSPATH')) {
exit; // Exit if accessed directly.
}
if (!class_exists('Tve_Dash_Growth_Tools_Config')) {
class Tve_Dash_Growth_Tools_Config
{
const REST_NAMESPACE = 'tve-dash/v1';
const REST_ROUTE = 'growth-tools';
public static function init()
{
static::hooks();
}
public static function hooks()
{
add_filter( 'tve_dash_admin_product_menu', array( __CLASS__, 'add_to_dashboard_menu' ) );
add_action('rest_api_init', [__CLASS__, 'register_rest_routes']);
add_filter('tve_dash_features', [__CLASS__, 'tve_dash_features']);
}
public static function add_to_dashboard_menu( $menus = array() ) {
$menus['growth_tools'] = array(
'parent_slug' => 'tve_dash_section',
'page_title' => __( 'About Us', 'thrive-dash' ),
'menu_title' => __( 'About Us', 'thrive-dash' ),
'capability' => TVE_DASH_CAPABILITY,
'menu_slug' => 'about_tve_theme_team',
'function' => 'tve_dash_growth_tools_dashboard',
);
return $menus;
}
public static function tve_dash_features( $enabled_features )
{
$enabled_features['growth_tools'] = true;
return $enabled_features;
}
public static function register_rest_routes()
{
if ( ! class_exists( 'Growth_Tools_Controller' ) ) {
require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . "Growth_Tools_Controller.php";
}
$growthToolsController = new Growth_Tools_Controller();
$growthToolsController->register_routes();
}
/**
* Load dependencies.
*/
protected function load_dependencies()
{
if ( ! function_exists( 'is_plugin_active' ) ) {
include_once ABSPATH . 'wp-admin/includes/plugin.php';
}
}
/**
* Retrieves a list of growth tools.
*
* @return array An array containing growth tools categorized by type.
*/
public static function growth_tools_list()
{
return apply_filters(
'tve_dash_growth_tools',
array(
'SEO and Analytics' => array(
array(
'plugin_slug' => 'all-in-one-seo-pack',
'name' => 'All in One SEO',
'path' => 'all-in-one-seo-pack/all_in_one_seo_pack.php',
'icon' => 'icon-all-in-one-seo',
'available_at_org' => true,
'status' => '',
'summary' => 'The original WordPress SEO plugin and toolkit that improves your website\'s search rankings. Comes with all the SEO features like Local SEO, WooCommerce SEO, sitemaps, SEO optimizer, schema, and more.',
'landing_url' => 'https://aioseo.com?utm_source=thrivethemes&utm_medium=link&utm_campaign=TTGrowthTools&utm_content='. TVE_DASH_VERSION,
'install_uri' => 'https://wordpress.org/plugins/all-in-one-seo-pack/',
'dashboard_uri' => admin_url( 'admin.php?page=aioseo' )
),
array(
'plugin_slug' => 'google-analytics-for-wordpress',
'name' => 'MonsterInsights',
'path' => 'google-analytics-for-wordpress/googleanalytics.php',
'icon' => 'icon-monster-insights',
'available_at_org' => true,
'status' => '',
'summary' => 'The leading WordPress analytics plugin that shows you how people find and use your website, so you can make data driven decisions to grow your business. Properly set up Google Analytics without writing code.',
'landing_url' => 'https://www.monsterinsights.com?utm_source=thrivethemes&utm_medium=link&utm_campaign=TTGrowthTools&utm_content='. TVE_DASH_VERSION,
'install_uri' => 'https://wordpress.org/plugins/google-analytics-for-wordpress/',
'dashboard_uri' => admin_url( 'admin.php?page=monsterinsights_settings' )
),
),
'Engagement and Social' => array(
array(
'plugin_slug' => 'pushengage',
'name' => 'PushEngage',
'path' => 'pushengage/main.php',
'icon' => 'icon-push-engage',
'available_at_org' => true,
'status' => '',
'summary' => 'Turn website visitors and app users into loyal fans and repeat customers with the best push notification software. 10,000+ businesses worldwide use PushEngage to grow repeat traffic, user engagement, and sales.',
'landing_url' => 'https://www.pushengage.com?utm_source=thrivethemes&utm_medium=link&utm_campaign=TTGrowthTools&utm_content='. TVE_DASH_VERSION,
'install_uri' => 'https://wordpress.org/plugins/pushengage/',
'dashboard_uri' => admin_url( 'admin.php?page=pushengage' )
),
array(
'plugin_slug' => 'instagram-feed',
'name' => 'Instagram Feeds',
'path' => 'instagram-feed/instagram-feed.php',
'icon' => 'icon-smash-balloon',
'available_at_org' => true,
'status' => '',
'summary' => 'Easily display Instagram content on your WordPress site without writing any code. Comes with multiple templates, ability to show content from multiple accounts, hashtags, and more. Trusted by 1 million websites.',
'landing_url' => 'https://smashballoon.com/instagram-feed?utm_source=thrivethemes&utm_medium=link&utm_campaign=TTGrowthTools&utm_content='. TVE_DASH_VERSION,
'install_uri' => 'https://wordpress.org/plugins/instagram-feed/',
'dashboard_uri' => admin_url( 'admin.php?page=sbi-feed-builder' )
),
array(
'plugin_slug' => 'custom-facebook-feed',
'name' => 'Facebook Feeds',
'path' => 'custom-facebook-feed/custom-facebook-feed.php',
'icon' => 'icon-smash-balloon',
'available_at_org' => true,
'status' => '',
'summary' => 'Easily display Facebook content on your WordPress site without writing any code. Comes with multiple templates, ability to embed albums, reviews, live videos, comments, and reactions.',
'landing_url' => 'https://smashballoon.com/custom-facebook-feed?utm_source=thrivethemes&utm_medium=link&utm_campaign=TTGrowthTools&utm_content='. TVE_DASH_VERSION,
'install_uri' => 'https://wordpress.org/plugins/custom-facebook-feed/',
'dashboard_uri' => admin_url( 'admin.php?page=cff-setup' )
),
array(
'plugin_slug' => 'custom-twitter-feeds',
'name' => 'Twitter Feeds',
'path' => 'custom-twitter-feeds/custom-twitter-feed.php',
'icon' => 'icon-smash-balloon',
'available_at_org' => true,
'status' => '',
'summary' => 'Easily display Twitter content in WordPress without writing any code. Comes with multiple layouts, ability to combine multiple Twitter feeds, Twitter card support, tweet moderation, and more.',
'landing_url' => 'https://smashballoon.com/custom-twitter-feeds?utm_source=thrivethemes&utm_medium=link&utm_campaign=TTGrowthTools&utm_content='. TVE_DASH_VERSION,
'install_uri' => 'https://wordpress.org/plugins/custom-twitter-feeds/',
'dashboard_uri' => admin_url( 'admin.php?page=ctf-feed-builder' )
),
array(
'plugin_slug' => 'feeds-for-youtube',
'name' => 'YouTube Feeds',
'path' => 'feeds-for-youtube/youtube-feed.php',
'icon' => 'icon-smash-balloon',
'available_at_org' => true,
'status' => '',
'summary' => 'Easily display YouTube videos on your WordPress site without writing any code. Comes with multiple layouts, ability to embed live streams, video filtering, ability to combine multiple channel videos, and more.',
'landing_url' => 'https://smashballoon.com/youtube-feed?utm_source=thrivethemes&utm_medium=link&utm_campaign=TTGrowthTools&utm_content='. TVE_DASH_VERSION,
'install_uri' => 'https://wordpress.org/plugins/feeds-for-youtube/',
'dashboard_uri' => admin_url( 'admin.php?page=sby-feed-builder' )
),
array(
'plugin_slug' => 'reviews-feed',
'name' => 'Review Feeds',
'path' => 'reviews-feed/sb-reviews.php',
'icon' => 'icon-smash-balloon',
'available_at_org' => true,
'status' => '',
'summary' => 'Easily display Google reviews, Yelp reviews, and more in a clean customizable feed. Comes with multiple layouts, customizable review content, leave-a-review link, review moderation, and more.',
'landing_url' => 'https://smashballoon.com/reviews-feed?utm_source=thrivethemes&utm_medium=link&utm_campaign=TTGrowthTools&utm_content='. TVE_DASH_VERSION,
'install_uri' => 'https://wordpress.org/plugins/reviews-feed/',
'dashboard_uri' => admin_url( 'admin.php?page=sbr' )
),
array(
'plugin_slug' => 'tiktok-feeds',
'name' => 'TikTok Feeds',
'path' => '',
'icon' => 'icon-smash-balloon',
'available_at_org' => false,
'status' => '',
'summary' => 'Embed feeds of your TikTok videos on your website -- from different accounts and in multiple layouts in just a few clicks!',
'landing_url' => 'https://smashballoon.com/tiktok-feeds?utm_source=thrivethemes&utm_medium=link&utm_campaign=TTGrowthTools&utm_content='. TVE_DASH_VERSION,
'install_uri' => '',
'dashboard_uri' => ''
),
array(
'plugin_slug' => 'thrive_quiz_builder',
'name' => 'Thrive Quiz Builder',
'path' => 'thrive-quiz-builder/thrive-quiz-builder.php',
'icon' => 'icon-thrive-quiz-builder',
'available_at_org' => false,
'status' => '',
'summary' => 'Easily build advanced online quizzes to better understand your audience, offer personalized product recommendations, segment your email list, and much more.',
'landing_url' => 'https://thrivethemes.com/quizbuilder?utm_source=thrivethemes&utm_medium=link&utm_campaign=TTGrowthTools&utm_content='. TVE_DASH_VERSION,
'install_uri' => '',
'dashboard_uri' => admin_url( 'admin.php?page=tqb_admin_dashboard' )
),
array(
'plugin_slug' => 'thrive_comments',
'name' => 'Thrive Comments',
'path' => '',
'icon' => 'icon-thrive-comments',
'available_at_org' => false,
'status' => '',
'summary' => 'Turn your blog comments section into an interactive experience with upvotes, social shares, gamified incentives, and more.',
'landing_url' => 'https://thrivethemes.com/comments?utm_source=thrivethemes&utm_medium=link&utm_campaign=TTGrowthTools&utm_content='. TVE_DASH_VERSION,
'install_uri' => '',
'dashboard_uri' => admin_url( 'admin.php?page=tcm_admin_dashboard' )
),
array(
'plugin_slug' => 'thrive_ovation',
'name' => 'Thrive Ovation',
'path' => 'thrive-ovation/thrive-ovation.php',
'icon' => 'icon-thrive-ovation',
'available_at_org' => false,
'status' => '',
'summary' => 'A powerful testimonial management system for WordPress. Effortlessly save and display testimonials to maximize social proof.',
'landing_url' => 'https://thrivethemes.com/ovation/?utm_source=thrivethemes&utm_medium=link&utm_campaign=TTGrowthTools&utm_content='. TVE_DASH_VERSION,
'install_uri' => '',
'dashboard_uri' => admin_url( 'admin.php?page=tvo_admin_dashboard' )
),
array(
'plugin_slug' => 'thrive_ultimatum',
'name' => 'Thrive Ultimatum',
'path' => 'thrive-ultimatum/thrive-ultimatum.php',
'icon' => 'icon-thrive-ultimatum',
'available_at_org' => false,
'status' => '',
'summary' => 'The #1 WordPress scarcity marketing tool to build advanced countdown timer campaigns.',
'landing_url' => 'https://thrivethemes.com/ultimatum/?utm_source=thrivethemes&utm_medium=link&utm_campaign=TTGrowthTools&utm_content='. TVE_DASH_VERSION,
'install_uri' => '',
'dashboard_uri' => admin_url( 'admin.php?page=tve_ult_dashboard' )
),
),
'Conversion Rate Optimization' => array(
array(
'plugin_slug' => 'trustpulse-api',
'name' => 'TrustPulse',
'path' => 'trustpulse-api/trustpulse.php',
'icon' => 'icon-trust-pulse',
'available_at_org' => true,
'status' => '',
'summary' => 'TrustPulse is the honest marketing platform that leverages and automates the real power of social proof to instantly increase trust, conversions and sales.',
'landing_url' => 'https://wordpress.org/plugins/trustpulse-api?utm_source=thrivethemes&utm_medium=link&utm_campaign=TTGrowthTools&utm_content='. TVE_DASH_VERSION,
'install_uri' => 'https://wordpress.org/plugins/trustpulse-api/',
'dashboard_uri' => admin_url( 'admin.php?page=trustpulse' )
),
array(
'plugin_slug' => 'affiliate-wp',
'name' => 'AffiliateWP',
'path' => '',
'icon' => 'icon-affiliate-wp',
'available_at_org' => false,
'status' => '',
'summary' => 'The #1 affiliate management plugin for WordPress. Easily create an affiliate program for your eCommerce store or membership site within minutes and start growing your sales with the power of referral marketing.',
'landing_url' => 'https://affiliatewp.com?utm_source=thrivethemes&utm_medium=link&utm_campaign=TTGrowthTools&utm_content='. TVE_DASH_VERSION,
'install_uri' => '',
'dashboard_uri' => ''
),
),
'Lead Generation' => array(
array(
'plugin_slug' => 'wpforms-lite',
'name' => 'WPForms',
'path' => 'wpforms-lite/wpforms.php',
'icon' => 'icon-am-wp-forms',
'available_at_org' => true,
'status' => '',
'summary' => 'The worlds most popular WordPress form builder, trusted by over 6 million websites. Get hundreds of pre-made templates so you can easily build contact forms, payment forms, and more.',
'landing_url' => 'https://wpforms.com?utm_source=thrivethemes&utm_medium=link&utm_campaign=TTGrowthTools&utm_content='. TVE_DASH_VERSION,
'install_uri' => 'https://wordpress.org/plugins/wpforms-lite/',
'dashboard_uri' => admin_url( 'admin.php?page=wpforms-overview' )
),
array(
'plugin_slug' => 'optinmonster',
'name' => 'OptinMonster',
'path' => 'optinmonster/optin-monster-wp-api.php',
'icon' => 'icon-am-optin-monster',
'available_at_org' => true,
'status' => '',
'summary' => 'Instantly get more subscribers, leads, and sales with the #1 conversion optimization toolkit. Create high converting popups, announcement bars, spin a wheel, and more with smart targeting and personalization.',
'landing_url' => 'https://wordpress.org/plugins/optinmonster?utm_source=thrivethemes&utm_medium=link&utm_campaign=TTGrowthTools&utm_content='. TVE_DASH_VERSION,
'install_uri' => 'https://wordpress.org/plugins/optinmonster/',
'dashboard_uri' => admin_url( 'admin.php?page=optin-monster-dashboard' )
),
array(
'plugin_slug' => 'rafflepress',
'name' => 'RafflePress',
'path' => 'rafflepress/rafflepress.php',
'icon' => 'icon-raffle-press',
'available_at_org' => true,
'status' => '',
'summary' => 'Turn your website visitors into brand ambassadors! Easily grow your email list, website traffic, and social media followers with the most powerful giveaways & contests plugin for WordPress.',
'landing_url' => 'https://rafflepress.com?utm_source=thrivethemes&utm_medium=link&utm_campaign=TTGrowthTools&utm_content='. TVE_DASH_VERSION,
'install_uri' => 'https://wordpress.org/plugins/rafflepress/',
'dashboard_uri' => admin_url( 'admin.php?page=rafflepress_lite' )
),
array(
'plugin_slug' => 'thrive_leads',
'name' => 'Thrive Leads',
'path' => '',
'icon' => 'icon-am-thrive-leads',
'available_at_org' => false,
'status' => '',
'summary' => 'Turn site visitors into engaged leads and build a more valuable mailing list faster.',
'landing_url' => 'https://thrivethemes.com/leads?utm_source=thrivethemes&utm_medium=link&utm_campaign=TTGrowthTools&utm_content='. TVE_DASH_VERSION,
'install_uri' => '',
'dashboard_uri' => admin_url( 'admin.php?page=thrive_leads_dashboard' )
),
),
'Email Marketing and Deliverability' => array(
array(
'plugin_slug' => 'wp-mail-smtp',
'name' => 'WP Mail SMTP',
'path' => 'wp-mail-smtp/wp_mail_smtp.php',
'icon' => 'icon-am-wp-mail-smtp',
'available_at_org' => true,
'status' => '',
'summary' => 'Make sure your WordPress emails always reach the recipient\'s inbox with the world\'s #1 SMTP plugin. Over 3,000,000 websites use WP Mail SMTP to fix their email deliverability issues.',
'landing_url' => 'https://wpmailsmtp.com?utm_source=thrivethemes&utm_medium=link&utm_campaign=TTGrowthTools&utm_content='. TVE_DASH_VERSION,
'install_uri' => 'https://wordpress.org/plugins/wp-mail-smtp/',
'dashboard_uri' => admin_url( 'admin.php?page=wp-mail-smtp' )
),
array(
'plugin_slug' => 'send-layer',
'name' => 'SendLayer',
'path' => '',
'icon' => 'icon-send-layer',
'available_at_org' => false,
'status' => '',
'summary' => 'Reliable email delivery made easy. Send your website emails with our API and SMTP relay for maximum deliverability, reliability, and scalability.',
'landing_url' => 'https://sendlayer.com?utm_source=thrivethemes&utm_medium=link&utm_campaign=TTGrowthTools&utm_content='. TVE_DASH_VERSION,
'install_uri' => '',
'dashboard_uri' => ''
),
),
'Essential WordPress Tools' => array(
array(
'plugin_slug' => 'insert-headers-and-footers',
'name' => 'WPCode',
'path' => 'insert-headers-and-footers/ihaf.php',
'icon' => 'icon-am-wp-code',
'available_at_org' => true,
'status' => '',
'summary' => 'Future proof your WordPress customizations with the most popular code snippet management plugin for WordPress. Trusted by over 1,500,000+ websites for easily adding code to WordPress right from the admin area.',
'landing_url' => 'https://wpcode.com?utm_source=thrivethemes&utm_medium=link&utm_campaign=TTGrowthTools&utm_content='. TVE_DASH_VERSION,
'install_uri' => 'https://wordpress.org/plugins/insert-headers-and-footers/',
'dashboard_uri' => admin_url( 'admin.php?page=wpcode' )
),
array(
'plugin_slug' => 'duplicator',
'name' => 'Duplicator',
'path' => 'duplicator/duplicator.php',
'icon' => 'icon-am-duplicator',
'available_at_org' => true,
'status' => '',
'summary' => 'Leading WordPress backup & site migration plugin. Over 1,500,000+ smart website owners use Duplicator to make reliable and secure WordPress backups to protect their websites. It also makes website migration really easy.',
'landing_url' => 'https://duplicator.com?utm_source=thrivethemes&utm_medium=link&utm_campaign=TTGrowthTools&utm_content='. TVE_DASH_VERSION,
'install_uri' => 'https://wordpress.org/plugins/duplicator/',
'dashboard_uri' => admin_url( 'admin.php?page=duplicator' )
),
),
'Ecommerce and Payments' => array(
array(
'plugin_slug' => 'charitable',
'name' => 'WP Charitable',
'path' => 'charitable/charitable.php',
'icon' => 'icon-wp-charitable',
'available_at_org' => true,
'status' => '',
'summary' => 'Top-rated WordPress donation and fundraising plugin. Over 10,000+ non-profit organizations and website owners use Charitable to create fundraising campaigns and raise more money online.',
'landing_url' => 'https://www.wpcharitable.com?utm_source=thrivethemes&utm_medium=link&utm_campaign=TTGrowthTools&utm_content='. TVE_DASH_VERSION,
'install_uri' => 'https://wordpress.org/plugins/charitable/',
'dashboard_uri' => admin_url( 'admin.php?page=charitable' )
),
),
'Course Management & Membership' => array(
array(
'plugin_slug' => 'thrive_apprentice',
'name' => 'Thrive Apprentice',
'path' => 'thrive-apprentice/thrive-apprentice.php',
'icon' => 'icon-thrive-apprentice',
'available_at_org' => false,
'status' => '',
'summary' => 'The #1 Membership and Course Builder for WordPress. Start creating attractive online courses and membership sites that sell with the most customizable LMS and Membership plugin available.',
'landing_url' => 'https://thrivethemes.com/apprentice?utm_source=thrivethemes&utm_medium=link&utm_campaign=TTGrowthTools&utm_content='. TVE_DASH_VERSION,
'install_uri' => '',
'dashboard_uri' => admin_url( 'admin.php?page=thrive_apprentice' )
),
),
'Website Builders' => array(
array(
'plugin_slug' => 'thrive-architect',
'name' => 'Thrive Architect',
'path' => '',
'icon' => 'icon-am-thrive-architect',
'available_at_org' => false,
'status' => '',
'summary' => 'The #1 WordPress page builder for deliberate marketers who have a vision of a conversion-focused website building.',
'landing_url' => 'https://thrivethemes.com/architect?utm_source=thrivethemes&utm_medium=link&utm_campaign=TTGrowthTools&utm_content='. TVE_DASH_VERSION,
'install_uri' => '',
'dashboard_uri' => admin_url( 'edit.php?post_type=page' )
),
array(
'plugin_slug' => 'thrive-theme-builder',
'name' => 'Thrive Theme Builder',
'path' => '',
'icon' => 'icon-am-thrive-theme-builder',
'available_at_org' => false,
'status' => '',
'summary' => 'Visually build the conversion focused site of your dreams no matter your experience level with the only marketing centered WordPress Theme Builder',
'landing_url' => 'https://thrivethemes.com/themebuilder?utm_source=thrivethemes&utm_medium=link&utm_campaign=TTGrowthTools&utm_content='. TVE_DASH_VERSION,
'install_uri' => '',
'dashboard_uri' => admin_url( 'admin.php?page=thrive-theme-dashboard' )
),
)
)
);
}
/**
* Categories.
*
* @return array
*/
public static function categories()
{
$items = apply_filters(
'tve_dash_growth_tools_category',
array(
10 => 'SEO and Analytics',
20 => 'Engagement and Social',
30 => 'Conversion Rate Optimization',
40 => 'Lead Generation',
50 => 'Email Marketing and Deliverability',
60 => 'Essential WordPress Tools',
70 => 'Ecommerce and Payments',
80 => 'Course Management & Membership',
90 => 'Website Builders',
)
);
ksort( $items );
return $items;
}
/**
* Retrieves tools ordered by category.
*
* @return array Tools ordered by category.
*/
protected function get_tools_order_by_category() {
$categories = $this->categories();
$tools_list = self::growth_tools_list();
$tools = [];
foreach ( $categories as $category ) {
$tools[ $category ] = $tools_list[ $category ];
}
return apply_filters( 'tve_dash_growth_tools_by_category', $tools );
}
/**
* Get the URL for a REST API route.
*
* @param string $endpoint The REST API endpoint.
* @param int $id Optional. The ID for the endpoint.
* @param array $args Optional. Additional arguments to append to the URL as query parameters.
* @return string The URL for the REST API route.
*/
public function tva_get_route_url( $endpoint, $id = 0, $args = array() ) {
$url = get_rest_url() . $this->namespace . '/' . $endpoint;
if ( ! empty( $id ) && is_numeric( $id ) ) {
$url .= '/' . $id;
}
if ( ! empty( $args ) ) {
$url = add_query_arg( $args, $url );
}
return $url;
}
/**
* Enqueue scripts and styles for the growth tools feature.
*/
protected function enqueue()
{
tve_dash_enqueue();
include TVE_DASH_PATH . '/inc/growth-tools/assets/css/growth-tools-icons.svg';
tve_dash_enqueue_style( 'tve-dash-growth-tools-css', TVE_DASH_URL . '/inc/growth-tools/assets/css/style.css' );
tve_dash_enqueue_script( 'tve-dash-growth-tools', TVE_DASH_URL . '/inc/growth-tools/assets/dist/growth-tools.min.js', array(
'tve-dash-main-js',
'jquery',
'backbone',
), false, true );
wp_localize_script( 'tve-dash-growth-tools', 'TVD_AM_CONST', array(
'baseUrl' => $this->tva_get_route_url( 'growth-tools' ),
'tools_category' => json_encode( $this->categories() ),
'is_TPM_installed' => is_TPM_installed(),
) );
}
/**
* Render a template.
*
* @param string $file Template file.
* @param array $data Template data.
*/
protected function render( $file, $data = array() ) {
if ( strpos( $file, '.php' ) === false ) {
$file .= '.php';
}
$file_path = $this->view_path . $file;
if ( ! is_file( $file_path ) ) {
echo 'No template found for ' . esc_html( $file );
return;
}
if ( ! empty( $data ) ) {
$this->data = array_merge_recursive( $this->data, $data );
}
include $file_path;
}
}
}

View File

@@ -0,0 +1,50 @@
<?php if ( empty( $this->messages['redirect'] ) ) :
?>
<div class="tve-about-us-content-wrapper">
<div class="tvd-header" id="tve-dash-gt-header">
<nav id="tvd-nav">
<div class="nav-wrapper">
<div class="tve-logo">
<a href="<?php echo admin_url( 'admin.php?page=tve_dash_section' ); ?>" class="tvd-users-dashboard-logo" title="Thrive Dashboard">
<span class="tvd-logo-container">
<img class="thrive_admin_logo" src="<?php echo TVE_DASH_URL ?>/css/images/thrive-logo.png" alt="Thrive Themes Logo">
</span>
</a>
</div>
</div>
</nav>
<div class="tve-about-us-content">
<div class="about-us">
<p>Hello and welcome to Thrive Themes, the most advanced yet simple-to-use suite of WordPress tools. We create conversion-focused software that helps you build a better online business.</p>
<p>Our mission is to provide you with everything you need to build a high-converting business <span>on your own,</span> one that turns visitors into subscribers, customers and raving fans.</p>
<p>Thrive Themes is brought to you by the same team behind the largest WordPress resource site,
<a href="https://www.wpbeginner.com?utm_source=thrivethemes&utm_medium=link&utm_campaign=TTGrowthTools&utm_content=<?php echo TVE_DASH_VERSION;?>" target="_blank">WP Beginner</a>, the best WordPress analytics plugin,
<a href="https://www.monsterinsights.com?utm_source=thrivethemes&utm_medium=link&utm_campaign=TTGrowthTools&utm_content=<?php echo TVE_DASH_VERSION;?>" target="_blank">MonsterInsights</a> and more!</p>
<p>Check out below other great tools that we recommend to help your online business grow even faster:</p>
</div>
<div class="the-tve-team">
<img class="image-behind-the-team" src="<?php echo TVE_DASH_URL ?>/css/images/team-behind-thrive-themes.png" alt="Team Behind Thrive Themes">
<span class="image-info">Part of the team behind Thrive Themes</span>
</div>
</div>
</div>
<div class="gt-page-header">
<div class="gt-page-header-left">
<span class="tvd-header-title">Integrations and connected apps</span>
<span class="tvd-header-summary">Recommended products that help you grow your business further</span>
</div>
<div class="tvd-filter">
<div class="tvd-filter-tools"></div>
<div class="tvd-filter-search">
<div class="tvd-search-elem"></div>
</div>
</div>
</div>
<div class="growth-tools-list"></div>
</div>
<?php endif ?>