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

Generate pages based on the selected goals and the Kadence Template Patterns API #251

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
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
13 changes: 10 additions & 3 deletions plugins/wme-sitebuilder/wme-sitebuilder/Container.php
Original file line number Diff line number Diff line change
Expand Up @@ -156,11 +156,18 @@ public function config() {


// Services.
Services\Domain::class => null,
Services\Logger::class => null,
Services\Domain::class => null,
Services\Goals::class => null,
Services\Logger::class => null,
Services\Kadence\Templates\ApiClient::class => null,

// Wizards.
Wizards\FirstTimeConfiguration::class => null,
Wizards\FirstTimeConfiguration::class => static function ( $app ) {
return new Wizards\FirstTimeConfiguration(
$app->make( Services\Kadence\Templates\ApiClient::class ),
$app->make( Services\Goals::class )
);
},
Wizards\GoLive::class => static function ( $app ) {
return new Wizards\GoLive(
$app->make( Contracts\ManagesDomain::class )
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

namespace StellarWP\PluginFramework\Exceptions;

use Tribe\WME\Sitebuilder\Exceptions\SitebuilderException;
use WP_Error;

/**
* A proper exception representation of a WP_Error object.
*/
class WPErrorException extends \RuntimeException implements SitebuilderException
{
/**
* @var WP_Error The underlying WP_Error object.
*/
protected $error;

/**
* Construct a new WPErrorException based on a WP_Error object.
*
* @param WP_Error $wp_error The WP_Error object to use as the basis for the exception.
*/
public function __construct(WP_Error $wp_error)
{
$this->error = $wp_error;

parent::__construct(
$wp_error->get_error_message(),
is_numeric($wp_error->get_error_code()) ? (int) $wp_error->get_error_code() : 0
);
}

/**
* Get the underlying WP_Error object.
*
* @return WP_Error The underlying WP_Error object.
*/
public function getError(): WP_Error
{
return $this->error;
}
}
105 changes: 105 additions & 0 deletions plugins/wme-sitebuilder/wme-sitebuilder/Services/Goals.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
<?php

namespace Tribe\WME\Sitebuilder\Services;

class Goals
{
const GOALS_BUSINESS = 'business';
const GOALS_ECOMMERCE = 'eCommerce';
const GOALS_BLOG = 'blog';
const GOALS_CAREERS = 'careers';
const GOALS_SERVICES = 'services';
const GOALS_PRICING_PLANS = 'pricingPlans';

/**
* Get the goal choices.
*
* @return array
*/
public function getChoices() {
$goals = [
[
'key' => self::GOALS_BUSINESS,
'value' => __( 'Create a home for myself, my business or organization online', 'wme-sitebuilder' ),
'description' => __( 'A web presence that shares information about my services, and expertise and helps customers find and get in contact with me.', 'wme-sitebuilder' ),
'icon' => 'WebAsset',
'requiredPages' => [
'home' => [
'title' => __( 'Home', 'wme-sitebuilder' ),
],
'about' => [
'title' => __( 'About', 'wme-sitebuilder' ),
],
'contact' => [
'title' => __( 'Contact', 'wme-sitebuilder' ),
],
],
'requiredPlugins' => [],
],
[
'key' => self::GOALS_ECOMMERCE,
'value' => __( 'Sell physical or digital goods online', 'wme-sitebuilder' ),
'description' => __( 'An ecommerce store to accept payment and manage customers.', 'wme-sitebuilder' ),
'icon' => 'ShoppingCart',
'requiredPages' => [
'shop' => [
'title' => __( 'Shop', 'wme-sitebuilder' ),
]
],
'requiredPlugins' => [
'woocommerce',
],
],
[
'key' => self::GOALS_BLOG,
'value' => __( 'Share news or write blogs', 'wme-sitebuilder' ),
'description' => __( 'Posting content is the primary goal of my organization or a core component of my website.', 'wme-sitebuilder' ),
'icon' => 'Article',
'requiredPages' => [
'blog' => [
'title' => __( 'News', 'wme-sitebuilder' ),
],
],
'requiredPlugins' => [],
],
[
'key' => self::GOALS_CAREERS,
'value' => __( 'Share open positions to potential candidates', 'wme-sitebuilder' ),
'description' => '',
'icon' => 'SupervisorAccount',
'requiredPages' => [
'careers' => [
'title' => __( 'Careers', 'wme-sitebuilder' ),
],
],
'requiredPlugins' => [],
],
[
'key' => self::GOALS_SERVICES,
'value' => __( 'Promote my services', 'wme-sitebuilder' ),
'description' => '',
'icon' => 'ChatBubble',
'requiredPages' => [
'services' => [
'title' => __( 'Services', 'wme-sitebuilder' ),
],
],
'requiredPlugins' => [],
],
[
'key' => self::GOALS_PRICING_PLANS,
'value' => __( 'Share my pricing plans', 'wme-sitebuilder' ),
'description' => __( 'A place to showcase each plan, with their benefits and prices.', 'wme-sitebuilder' ),
'icon' => 'PriceChange',
'requiredPages' => [
'pricing' => [
'title' => __( 'Plans (Pricing)', 'wme-sitebuilder' ),
],
],
'requiredPlugins' => [],
],
];

return apply_filters( 'wme_sitebuilder_ftc_wizard_goals', $goals );
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
<?php

namespace Tribe\WME\Sitebuilder\Services\Kadence\Templates;

use StellarWP\PluginFramework\Exceptions\WPErrorException;
use WP_Error;

class ApiClient
{

/**
* @var string $url The URL of the Kadence Template Patterns Cloud API.
*/
private $url = 'https://patterns.startertemplatecloud.com';

/**
* Fetch the Kadence Template Patterns Cloud API
*
* @throws WPErrorException If an error occurs making the request.
*
* @return Array<string,mixed> An array containing all page templates sorted by type.Z
*/
public function fetch_page_patterns()
{
$pages = wp_cache_get( 'wme_ktp_pages' );

if (! $pages) {
$response = $this->fetch_patterns(Types::PAGES);
$body = json_decode($response['body'], true);

foreach ( TYPES::get_page_types() as $type ) {
$pages[$type] = array_filter( $body, function ($item) use ($type) {
return in_array( $type, array_keys($item['categories']));
});
}

wp_cache_set( 'wme_ktp_pages', $pages, '', 60 * 60 * 24 );
}

// slug => string
// name => string
// categories => array (use as is)
// keywords => array (use as is)
// pro => bool
// locked => bool
// content => string (ignore)
// html => string (ignore)
// rows_htmls => gutenberg blocks
// rows => array
// description => string
// image => url
// imageW => int
// imageH => int
return $pages;
}

/**
* Fetch the Kadence Template Patterns Cloud API
*
* @param string $type The type of pattern to fetch.
* @param mixed[] $args Optional. WP HTTP API arguments, which will be merged with defaults.
* {@link https://developer.wordpress.org/reference/classes/WP_Http/request/#parameters}.
*
* @throws WPErrorException If an error occurs making the request.
*
* @return Array<string,mixed> An array containing the following keys: 'headers', 'body', 'response', 'cookies',
* and 'filename'. This is the same as {@see \WP_HTTP::request()}
*/
public function fetch_patterns(string $type, array $args = [])
{
if (!Types::is_valid_type($type)) {
return new WP_Error('invalid_type', sprintf('The type %s is not valid.', $type));
}

$response = wp_remote_request(
esc_url_raw(sprintf('%1$s/wp-json/kadence-cloud/v1/pages/?key=%2$s', $this->url, $type)),
array_replace_recursive([
'user-agent' => 'StellarWP/WME/PartnerCloud',
'timeout' => 30,
'headers' => [
'Accept' => 'application/json',
],
], $args)
);

if (is_wp_error($response)) {
throw new WPErrorException($response);
}

return $response;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?php

namespace Tribe\WME\Sitebuilder\Services\Kadence\Templates;

final class Types
{
/**
* The available types of patterns.
*/
public const SECTIONS = 'sections';
public const PAGES = 'pages';

/**
* The available types of pages.
*/
public const HOME = 'home';
public const SERVICES = 'services';
public const CONTACT = 'contact';
public const ABOUT = 'about';
public const CAREERS = 'careers';
public const PRICING = 'pricing';
public const BLOG = 'blog';

/**
* Get the available types of patterns.
*
* @return string[]
*/
public static function get_types(): array
{
return [
self::SECTIONS,
self::PAGES
];
}

/**
* Check if a type is valid.
*
* @param string $type The type to check.
*
* @return bool
*/
public static function is_valid_type(string $type): bool
{
return in_array($type, self::get_types());
}

/**
* Get the available types of pages.
*
* @return string[]
*/
public static function get_page_types(): array
{
return [
self::HOME,
self::SERVICES,
self::CONTACT,
self::ABOUT,
self::CAREERS,
self::PRICING,
self::BLOG
];
}
}
Loading