├── .editorconfig
├── .gitignore
├── README.md
├── composer.json
├── publishes
├── app
│ └── wc-template-hooks.php
└── resources
│ └── views
│ ├── archive-product.blade.php
│ └── single-product.blade.php
└── src
├── WooCommerce.php
└── WooCommerceServiceProvider.php
/.editorconfig:
--------------------------------------------------------------------------------
1 | # editorconfig.org
2 |
3 | root = true
4 |
5 | [*]
6 | indent_style = space
7 | indent_size = 2
8 | end_of_line = lf
9 | charset = utf-8
10 | trim_trailing_whitespace = true
11 | insert_final_newline = true
12 |
13 | [*.php]
14 | indent_size = 4
15 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | vendor
2 | composer.lock
3 | .idea/
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Sage WooCommerce
2 |
3 | Add WooCommerce support to Sage 10.
4 |
5 | ## Installation
6 |
7 | Install the composer package.
8 |
9 | composer require generoi/sage-woocommerce
10 |
11 | Add the package to the cached package manifest.
12 |
13 | wp acorn package:discover
14 |
15 | Publish the required `single-product.blade.php` and `archive-product.blade.php` views.
16 |
17 | wp acorn vendor:publish --tag="woocommerce-template-views"
18 |
19 | Optionally publish a commented out `app/wc-template-hooks.php` file for customizing the WC template hooks.
20 |
21 | wp acorn vendor:publish --tag="woocommerce-template-hooks"
22 |
23 | By default your theme has now declared WooCommerce support. To add support for specific features, add them to your `app/setup.php`
24 |
25 | ```php
26 | add_theme_support('wc-product-gallery-zoom');
27 | add_theme_support('wc-product-gallery-lightbox');
28 | add_theme_support('wc-product-gallery-slider');
29 | ```
30 |
31 | ## Filters
32 |
33 | ```php
34 | /**
35 | * Add support for WooCommerce Subscription templates.
36 | */
37 | add_filter('sage-woocommerce/templates', function ($paths) {
38 | $paths[] = WP_PLUGIN_DIR . '/woocommerce-subscriptions/templates/';
39 | return $paths;
40 | });
41 | ```
42 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "generoi/sage-woocommerce",
3 | "type": "library",
4 | "license": "MIT",
5 | "description": "",
6 | "homepage": "https://github.com/generoi/sage-woocommerce",
7 | "authors": [
8 | {
9 | "name": "Oskar Schöldström",
10 | "email": "public@oxy.fi"
11 | }
12 | ],
13 | "autoload": {
14 | "psr-4": {
15 | "Genero\\Sage\\WooCommerce\\": "src/"
16 | }
17 | },
18 | "require": {
19 | "roots/acorn": "*"
20 | },
21 | "require-dev": {
22 | "squizlabs/php_codesniffer": "~3.0"
23 | },
24 | "minimum-stability": "dev",
25 | "prefer-stable": true,
26 | "scripts": {
27 | "test": [
28 | "phpcs --ignore=vendor --extensions=php --standard=PSR2 ."
29 | ]
30 | },
31 | "archive" : {
32 | "exclude": [
33 | ".gitignore"
34 | ]
35 | },
36 | "extra": {
37 | "acorn": {
38 | "providers": [
39 | "Genero\\Sage\\WooCommerce\\WooCommerceServiceProvider"
40 | ]
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/publishes/app/wc-template-hooks.php:
--------------------------------------------------------------------------------
1 |
26 | @if (apply_filters('woocommerce_show_page_title', true))
27 |
28 | @endif
29 |
30 | @php
31 | do_action('woocommerce_archive_description')
32 | @endphp
33 |
34 |
35 | @if (woocommerce_product_loop())
36 | @php
37 | do_action('woocommerce_before_shop_loop');
38 | woocommerce_product_loop_start();
39 | @endphp
40 |
41 | @if (wc_get_loop_prop('total'))
42 | @while (have_posts())
43 | @php
44 | the_post();
45 | do_action('woocommerce_shop_loop');
46 | wc_get_template_part('content', 'product');
47 | @endphp
48 | @endwhile
49 | @endif
50 |
51 | @php
52 | woocommerce_product_loop_end();
53 | do_action('woocommerce_after_shop_loop');
54 | @endphp
55 | @else
56 | @php
57 | do_action('woocommerce_no_products_found')
58 | @endphp
59 | @endif
60 |
61 | @php
62 | do_action('woocommerce_after_main_content');
63 | do_action('get_sidebar', 'shop');
64 | do_action('get_footer', 'shop');
65 | @endphp
66 | @endsection
67 |
--------------------------------------------------------------------------------
/publishes/resources/views/single-product.blade.php:
--------------------------------------------------------------------------------
1 | {{--
2 | The Template for displaying all single products
3 |
4 | This template can be overridden by copying it to yourtheme/woocommerce/single-product.php.
5 |
6 | HOWEVER, on occasion WooCommerce will need to update template files and you
7 | (the theme developer) will need to copy the new files to your theme to
8 | maintain compatibility. We try to do this as little as possible, but it does
9 | happen. When this occurs the version of the template file will be bumped and
10 | the readme will list any important changes.
11 |
12 | @see https://docs.woocommerce.com/document/template-structure/
13 | @package WooCommerce\Templates
14 | @version 1.6.4
15 | --}}
16 |
17 | @extends('layouts.app')
18 |
19 | @section('content')
20 | @php
21 | do_action('get_header', 'shop');
22 | do_action('woocommerce_before_main_content');
23 | @endphp
24 |
25 | @while(have_posts())
26 | @php
27 | the_post();
28 | wc_get_template_part('content', 'single-product');
29 | @endphp
30 | @endwhile
31 |
32 | @php
33 | do_action('woocommerce_after_main_content');
34 | do_action('get_sidebar', 'shop');
35 | do_action('get_footer', 'shop');
36 | @endphp
37 | @endsection
38 |
--------------------------------------------------------------------------------
/src/WooCommerce.php:
--------------------------------------------------------------------------------
1 | app = $app;
24 | $this->fileFinder = $fileFinder;
25 | $this->sageFinder = $sageFinder;
26 | }
27 |
28 | /**
29 | * Load template hook overrides file if available in app/ folder of theme.
30 | */
31 | public function loadThemeTemplateHooks()
32 | {
33 | locate_template('app/wc-template-hooks.php', true, true);
34 | }
35 |
36 | /**
37 | * Declare theme support.
38 | */
39 | public function addThemeSupport(): void
40 | {
41 | add_theme_support('woocommerce');
42 | }
43 |
44 | /**
45 | * Support blade templates for the main template include.
46 | */
47 | public function templateInclude(string $template): string
48 | {
49 | if (!$this->isWooCommerceTemplate($template)) {
50 | return $template;
51 | }
52 | return $this->locateThemeTemplate($template) ?: $template;
53 | }
54 |
55 | /**
56 | * Support blade templates for the woocommerce comments/reviews.
57 | */
58 | public function reviewsTemplate(string $template): string
59 | {
60 | if (!$this->isWooCommerceTemplate($template)) {
61 | return $template;
62 | }
63 |
64 | return $this->template($template);
65 | }
66 |
67 | /**
68 | * Filter a template path, taking into account theme templates and creating
69 | * blade loaders as needed.
70 | */
71 | public function template(string $template, string $templateName = ''): string
72 | {
73 | // Locate any matching template within the theme.
74 | $themeTemplate = $this->locateThemeTemplate($templateName ?: $template);
75 | if (!$themeTemplate) {
76 | return $template;
77 | }
78 |
79 | // Return filename for status screen
80 | if (
81 | is_admin() &&
82 | !wp_doing_ajax() &&
83 | get_current_screen() &&
84 | get_current_screen()->id === 'woocommerce_page_wc-status'
85 | ) {
86 | return $themeTemplate;
87 | }
88 |
89 | // Include directly unless it's a blade file.
90 | if (!Str::endsWith($themeTemplate, '.blade.php')) {
91 | return $themeTemplate;
92 | }
93 |
94 | // We have a template, create a loader file and return it's path.
95 | return view(
96 | $this->fileFinder->getPossibleViewNameFromPath(realpath($themeTemplate))
97 | )->makeLoader();
98 | }
99 |
100 | /**
101 | * Check if template is a WooCommerce template.
102 | */
103 | protected function isWooCommerceTemplate(string $template): bool
104 | {
105 | return $this->relativeTemplatePath($template) !== $template;
106 | }
107 |
108 | /**
109 | * Return the theme relative template path.
110 | */
111 | protected function relativeTemplatePath(string $template): string
112 | {
113 | $defaultPaths = [
114 | // WooCommerce plugin templates
115 | \WC_ABSPATH . 'templates/',
116 | ];
117 |
118 | if (is_child_theme()) {
119 | // Parent theme templates in woocommerce/ subfolder.
120 | $defaultPaths[] = get_template_directory() . '/' . WC()->template_path();
121 | }
122 |
123 | return str_replace(
124 | apply_filters('sage-woocommerce/templates', $defaultPaths),
125 | '',
126 | $template
127 | );
128 | }
129 |
130 | /**
131 | * Locate the theme's WooCommerce blade template when available.
132 | */
133 | protected function locateThemeTemplate(string $template): string
134 | {
135 | // Absolute plugin template path -> woocommerce/single-product.php
136 | $themeTemplate = WC()->template_path() . $this->relativeTemplatePath($template);
137 | // Return absolute theme template path.
138 | return locate_template($this->sageFinder->locate($themeTemplate));
139 | }
140 | }
141 |
--------------------------------------------------------------------------------
/src/WooCommerceServiceProvider.php:
--------------------------------------------------------------------------------
1 | app->singleton('woocommerce', WooCommerce::class);
17 | }
18 |
19 | /**
20 | * Bootstrap any application services.
21 | *
22 | * @return void
23 | */
24 | public function boot()
25 | {
26 | if (defined('WC_ABSPATH')) {
27 | $this->app['woocommerce']->loadThemeTemplateHooks();
28 | $this->bindSetupAction();
29 | $this->bindFilters();
30 | }
31 |
32 | $this->publishes([
33 | __DIR__ . '/../publishes/resources/views' => $this->app->resourcePath('views/woocommerce'),
34 | ], 'woocommerce-template-views');
35 |
36 | $this->publishes([
37 | __DIR__ . '/../publishes/app/wc-template-hooks.php' => $this->app->path('wc-template-hooks.php'),
38 | ], 'woocommerce-template-hooks');
39 | }
40 |
41 | public function bindFilters()
42 | {
43 | $woocommerce = $this->app['woocommerce'];
44 |
45 | add_filter('template_include', [$woocommerce, 'templateInclude'], 11);
46 | add_filter('woocommerce_locate_template', [$woocommerce, 'template'], 11, 2);
47 | add_filter('woocommerce_locate_core_template', [$woocommerce, 'template'], 10, 2);
48 | add_filter('wc_get_template_part', [$woocommerce, 'template']);
49 | add_filter('wc_get_template', [$woocommerce, 'template'], 1000);
50 | add_filter('comments_template', [$woocommerce, 'reviewsTemplate'], 11);
51 | }
52 |
53 | public function bindSetupAction()
54 | {
55 | if (doing_action('after_setup_theme')) {
56 | $this->app['woocommerce']->addThemeSupport();
57 | } else {
58 | add_action('after_setup_theme', [$this->app['woocommerce'], 'addThemeSupport']);
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------