Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/pattern version control #20

Merged
merged 3 commits into from
Aug 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
288 changes: 288 additions & 0 deletions inc/functions/class-wdsbtthemepatternmanager.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,288 @@
<?php
/**
* Theme Pattern Manager
*
* This file contains the code to add import and export buttons for block patterns
* to the list of posts showing the post type 'wp_block'.
*
* @package YourTheme
* @subpackage WdsbtThemePatternManager
* @since 1.0.0
*/

/**
* Class WdsbtThemePatternManager
*
* Handles the import and export functionality for block patterns.
*
* @since 1.0.0
*/
class WdsbtThemePatternManager {

/**
* WdsbtThemePatternManager constructor.
*
* Registers the necessary hooks.
*
* @since 1.0.0
*/
public function __construct() {
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
add_action( 'admin_footer-edit.php', array( $this, 'add_import_export_buttons' ) );
add_action( 'wp_ajax_import_patterns', array( $this, 'import_patterns' ) );
add_action( 'wp_ajax_export_patterns', array( $this, 'export_patterns' ) );
}

/**
* Enqueue scripts for the admin area.
*
* @param string $hook The current admin page.
*
* @since 1.0.0
*/
public function enqueue_scripts( $hook ) {
if ( 'edit.php' !== $hook || get_current_screen()->post_type !== 'wp_block' ) {
return;
}
wp_enqueue_script(
'pattern-manager-script',
get_template_directory_uri() . '/pattern-manager.js',
array( 'jquery' ),
'1.0',
true
);
wp_localize_script(
'pattern-manager-script',
'PatternManagerAjax',
array(
'ajax_url' => admin_url( 'admin-ajax.php' ),
'nonce' => wp_create_nonce( 'pattern_manager_nonce' ),
)
);
}
/**
* Helper function to check the existence of a post slug in the database.
*
* @param string $post_name Slug of the WordPress Post.
*
* @since 1.0.0
*/
public function the_slug_exists( $post_name ) {
global $wpdb;
if ( $wpdb->get_row( 'SELECT post_name FROM wp_posts WHERE post_name = %d', $post_name ) ) {
return true;
} else {
return false;
}
}


/**
* Add import and export buttons to the post list for 'wp_block' post type.
*
* @since 1.0.0
*/
public function add_import_export_buttons() {
if ( get_current_screen()->post_type !== 'wp_block' ) {
return;
}
?>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', function () {
// Create button group div
const buttonGroup = document.createElement('div');
buttonGroup.className = 'alignleft actions';
buttonGroup.innerHTML = '<br />';

// Create import button
const importButton = document.createElement('button');
importButton.type = 'button';
importButton.className = 'button';
importButton.textContent = 'Import Patterns';

// Create export button
const exportButton = document.createElement('button');
exportButton.type = 'button';
exportButton.className = 'button';
exportButton.textContent = 'Export Patterns';

// Event listener for import button
importButton.addEventListener('click', function () {
if (confirm('Are you sure you want to import patterns from patterns.json?')) {
fetch(PatternManagerAjax.ajax_url, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
action: 'import_patterns',
nonce: PatternManagerAjax.nonce,
}),
})
.then(response => response.json())
.then(response => {
if (response.success) {
alert('Patterns imported successfully');
location.reload();
} else {
alert('Error: ' + response.data);
}
})
.catch(error => console.error('Error:', error));
}
});

// Event listener for export button
exportButton.addEventListener('click', function () {
if (confirm('Are you sure you want to export patterns to patterns.json?')) {
fetch(PatternManagerAjax.ajax_url, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
action: 'export_patterns',
nonce: PatternManagerAjax.nonce,
}),
})
.then(response => response.json())
.then(response => {
if (response.success) {
alert('Patterns exported successfully');
} else {
alert('Error: ' + response.data);
}
})
.catch(error => console.error('Error:', error));
}
});

// Append buttons to button group
buttonGroup.appendChild(importButton);
buttonGroup.appendChild(exportButton);

// Append button group after .wp-list-table
document.querySelector('.wp-list-table').after(buttonGroup);
});
</script>
<?php
}

/**
* Import patterns from the patterns.json file.
*
* @since 1.0.0
*/
public function import_patterns() {
check_ajax_referer( 'pattern_manager_nonce', 'nonce' );

$file = get_template_directory() . '/patterns.json';
global $wp_filesystem;
if ( ! WP_Filesystem() ) {
wp_send_json_error( 'Filesystem initialization error' );
}

if ( ! $wp_filesystem->exists( $file ) ) {
wp_send_json_error( 'File not found' );
}

$patterns_json = $wp_filesystem->get_contents( $file );
$patterns = json_decode( $patterns_json, true );

if ( json_last_error() !== JSON_ERROR_NONE ) {
wp_send_json_error( 'Invalid JSON format' );
}

foreach ( $patterns as $pattern ) {
if ( ! isset( $pattern['title'] ) ) {
continue;
}

$pattern_assembly = array(
'post_title' => wp_strip_all_tags( $pattern['title'] ),
'post_content' => $pattern['content'],
'post_status' => $pattern['status'],
'post_author' => 1,
'post_type' => 'wp_block',
);

if ( ! $this->the_slug_exists( $pattern['slug'] ) || 'draft' === $pattern['status'] ) {
$new_post_id = wp_insert_post( $pattern_assembly );
wp_set_object_terms( $new_post_id, $pattern['categories'], 'wp_pattern_category' );
} else {
$pattern_assembly['ID'] = url_to_postid( $pattern['slug'] );
$new_post_id = wp_update_post( $pattern_assembly );
wp_set_object_terms( $new_post_id, $pattern['categories'], 'wp_pattern_category' );
}
}

wp_send_json_success( 'Patterns imported successfully' );
}

/**
* Export patterns to the patterns.json file.
*
* @since 1.0.0
*/
public function export_patterns() {
check_ajax_referer( 'pattern_manager_nonce', 'nonce' );

$args = array(
'post_type' => 'wp_block',
);
$patterns = new WP_Query( $args );

$patterns_array = array();

if ( $patterns->have_posts() ) {
while ( $patterns->have_posts() ) {
global $post;
$patterns->the_post();

$categories = get_the_terms( $post->id, 'wp_pattern_category' );
$categories_array = array();

foreach ( $categories as $category ) :
$categories_array[] = $category->name;
endforeach;

$patterns_array[] = array(
'title' => wp_kses_post( get_the_title() ),
'slug' => wp_kses_post( $post->post_name ),
'categories' => $categories_array,
'content' => wp_kses_post( get_the_content() ),
'status' => wp_kses_post( get_post_status() ),
);
}
} else {
wp_send_json_error( 'No Patterns Registered' );
end;
}

wp_reset_postdata();

$file = get_template_directory() . '/patterns.json';
global $wp_filesystem;
if ( ! WP_Filesystem() ) {
wp_send_json_error( 'Filesystem initialization error' );
}

$result = $wp_filesystem->put_contents( $file, wp_json_encode( $patterns_array, JSON_PRETTY_PRINT ) );

if ( ! $result ) {
wp_send_json_error( 'Error writing to file' );
}

wp_send_json_success( 'Patterns exported successfully' );
}
}

new WdsbtThemePatternManager();

/**
* End of Theme Pattern Manager class.
*
* @since 1.0.0
* @package YourTheme
* @subpackage WdsbtThemePatternManager
*/
75 changes: 75 additions & 0 deletions pattern-manager.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
window.onload = function () {
document.addEventListener('DOMContentLoaded', function () {
document
.getElementById('import-button')
.addEventListener('click', function () {
if (
// eslint-disable-next-line no-alert
confirm(
'Are you sure you want to import patterns from patterns.json?'
)
) {
// eslint-disable-next-line no-undef
fetch(PatternManagerAjax.ajax_url, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
action: 'import_patterns',
// eslint-disable-next-line no-undef
nonce: PatternManagerAjax.nonce,
}),
})
.then((response) => response.json())
.then((response) => {
if (response.success) {
// eslint-disable-next-line no-alert
alert('Patterns imported successfully');
} else {
// eslint-disable-next-line no-alert
alert('Error: ' + response.data);
}
})
// eslint-disable-next-line no-console
.catch((error) => console.error('Error:', error));
}
});

document
.getElementById('export-button')
.addEventListener('click', function () {
if (
// eslint-disable-next-line no-alert
confirm(
'Are you sure you want to export patterns to patterns.json?'
)
) {
// eslint-disable-next-line no-undef
fetch(PatternManagerAjax.ajax_url, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
action: 'export_patterns',
// eslint-disable-next-line no-undef
nonce: PatternManagerAjax.nonce,
}),
})
.then((response) => response.json())
.then((response) => {
if (response.success) {
// eslint-disable-next-line no-alert
alert('Patterns exported successfully');
} else {
// eslint-disable-next-line no-alert
alert('Error: ' + response.data);
}
})
// eslint-disable-next-line no-console
.catch((error) => console.error('Error:', error));
}
});
});
};
1 change: 1 addition & 0 deletions patterns.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
Loading