PluginProbe
Templately – Elementor & Gutenberg Template Library: 6500+ Free & Pro Ready Templates And Cloud! / 3.7.3
Templately – Elementor & Gutenberg Template Library: 6500+ Free & Pro Ready Templates And Cloud! v3.7.3
3.7.5 3.7.4 3.7.3 3.7.2 1-final 3.7.1 3.7.0 3.6.8 3.6.7 3.6.6 3.6.5 3.6.4 3.6.3 3.6.2 3.6.1 3.0.3 3.0.4 3.0.5 3.0.6 3.0.7 3.0.8 3.0.9 3.1.0 3.1.1 3.1.10 All 111 releases
templately / includes / Plugin.php

Plugin.php in Templately – Elementor & Gutenberg Template Library: 6500+ Free & Pro Ready Templates And Cloud! 3.7.3, at includes/Plugin.php

374 lines 10.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Templately plugin.
4 *
5 * The main plugin handler class is responsible for initializing Templately. The
6 * class registers and all the components required to run the plugin.
7 *
8 * @package Templately
9 */
10
11 namespace Templately;
12
13 use Templately\Admin\API\Settings as APISettings;
14 use Templately\Admin\Settings;
15 use Templately\API\AIContent;
16 use Templately\API\LogoGeneration;
17 use Templately\API\Conditions;
18 use Templately\API\ThemeBuilderApi;
19 use Templately\Builder\ThemeBuilder;
20 use Templately\Core\Importer\FullSiteImport;
21 use Templately\Utils\AuthErrorCode;
22 use Templately\Utils\Base;
23 use Templately\Utils\Database;
24 use Templately\Utils\Enqueue;
25
26 use Templately\Core\Admin;
27 use Templately\Core\Module;
28
29 use Templately\API\Tags;
30 use Templately\API\Items;
31 use Templately\API\Login;
32 use Templately\API\Checkout;
33 use Templately\API\SignUp;
34 use Templately\API\AiCredit;
35 use Templately\API\Profile;
36 use Templately\API\Import;
37 use Templately\API\MyClouds;
38 use Templately\API\WorkSpaces;
39 use Templately\API\Categories;
40 use Templately\API\Dependencies;
41 use Templately\API\TemplateTypes;
42 use Templately\API\SavedTemplates;
43 use Templately\API\Sites;
44 use Templately\API\Tour;
45 use Templately\Core\DeactivationSurvey;
46 use Templately\Core\Maintenance;
47 use Templately\Core\Migrator;
48 use Templately\Core\Platform\Gutenberg;
49 use Templately\Core\Platform\Elementor;
50
51 final class Plugin extends Base {
52 public $version = '3.7.3';
53
54 public $admin;
55 public $settings;
56 /**
57 * Enqueue class responsible for assets
58 * @var Enqueue
59 */
60 public $assets;
61
62 /**
63 * @var ThemeBuilder
64 */
65 public $theme_builder;
66
67 /**
68 * @var Developer
69 */
70 public $developer;
71
72 /**
73 * Plugin constructor.
74 * Initializing Templately plugin.
75 *
76 * @access private
77 */
78 public function __construct() {
79 $this->define_constants();
80 $this->set_locale();
81
82 Maintenance::init();
83 DeactivationSurvey::init();
84
85 $this->assets = Enqueue::get_instance( TEMPLATELY_URL, TEMPLATELY_PATH, $this->version );
86 $this->admin = Admin::get_instance();
87 $this->settings = Settings::get_instance();
88 $this->theme_builder = ThemeBuilder::get_instance();
89
90 // Initialize developer functionality if available
91 $this->init_developer_functionality();
92
93 add_action( 'plugins_loaded', [ $this, 'plugins_loaded' ] );
94 add_action( 'rest_api_init', [ $this, 'register_routes' ] );
95
96 add_action( 'init', [ $this, 'google_login_handler' ] );
97
98 /**
99 * Initialize.
100 */
101 do_action( 'templately_init' );
102
103 }
104
105 /**
106 * Cloning is forbidden.
107 *
108 * @since 2.0
109 */
110 public function __clone() {
111 _doing_it_wrong( __FUNCTION__, __( 'Cloning is forbidden.', 'templately' ), '2.0' );
112 }
113
114 /**
115 * Un-serializing instances of this class is forbidden.
116 *
117 * @since 2.0
118 */
119 public function __wakeup() {
120 _doing_it_wrong( __FUNCTION__, __( 'Un-serializing instances of this class is forbidden.', 'templately' ), '2.0' );
121 }
122
123 /**
124 * Initializing Things on Plugins Loaded
125 * @return void
126 */
127 public function plugins_loaded() {
128 $this->platforms(); // PLATFORMS LOADED
129 $this->apis(); // APIs LOADED
130
131 /**
132 * Migrator for Templately
133 */
134 Migrator::get_instance();
135
136 /**
137 * Full Site Import
138 */
139 FullSiteImport::get_instance();
140 }
141
142 /**
143 * Initialize developer functionality if available
144 *
145 * This method safely loads developer functionality only if the developer
146 * directory and class exist, preventing fatal errors in production builds.
147 *
148 * @return void
149 */
150 private function init_developer_functionality() {
151 $developer_file = TEMPLATELY_PATH . 'includes/Core/Developer/Developer.php';
152
153 // Check if developer file exists before attempting to load
154 if ( file_exists( $developer_file ) ) {
155 // Include the developer class file
156 require_once $developer_file;
157
158 // Check if the class exists after including the file
159 if ( class_exists( '\\Templately\\Core\\Developer\\Developer' ) ) {
160 $this->developer = \Templately\Core\Developer\Developer::get_instance();
161 }
162 }
163
164 // If developer functionality is not available, set to null
165 if ( ! isset( $this->developer ) ) {
166 $this->developer = null;
167 }
168 }
169
170
171
172 /**
173 * Initialize all platforms
174 * @return void
175 */
176 public function platforms() {
177 Gutenberg::get_instance();
178 Elementor::get_instance();
179 }
180
181 /**
182 * All the API instantiated
183 *
184 * @return void
185 */
186 private function apis() {
187 Conditions::get_instance();
188 Categories::get_instance();
189 TemplateTypes::get_instance();
190 Dependencies::get_instance();
191 Tags::get_instance();
192 ThemeBuilderApi::get_instance();
193
194 AIContent::get_instance();
195 LogoGeneration::get_instance();
196 Items::get_instance();
197 SavedTemplates::get_instance();
198
199 Login::get_instance();
200 Checkout::get_instance();
201 SignUp::get_instance();
202 Import::get_instance();
203 Profile::get_instance();
204 AiCredit::get_instance();
205 MyClouds::get_instance();
206 WorkSpaces::get_instance();
207 Sites::get_instance();
208 Tour::get_instance();
209
210 APISettings::get_instance();
211 // Note: DeveloperSettings::get_instance() is called in Developer::init_modules() when developer functionality is available and enabled
212 }
213
214 /**
215 * Register all REST API endpoints
216 * @return void
217 */
218 public function register_routes() {
219 if ( ! empty( $modules = Module::get_instance()->get( 'API' ) ) ) {
220 foreach ( $modules as $module ) {
221 $module->object->register_routes();
222 }
223 }
224 }
225
226 /**
227 * Define CONSTANTS
228 *
229 * @return void
230 * @since 2.0.0
231 */
232 public function define_constants() {
233 $this->define( 'TEMPLATELY_URL', plugin_dir_url( TEMPLATELY_FILE ) );
234 $this->define( 'TEMPLATELY_ASSETS', TEMPLATELY_URL . 'assets/' );
235 $this->define( 'TEMPLATELY_PLUGIN_BASENAME', plugin_basename( TEMPLATELY_FILE ) );
236 $this->define( 'TEMPLATELY_VERSION', $this->version );
237 $this->define( 'TEMPLATELY_API_NAMESPACE', 'templately/v1' );
238 $this->define( 'TEMPLATELY_VIEWS_ABSPATH', TEMPLATELY_PATH . 'views/' );
239 }
240
241 /**
242 * Define constant if not already set.
243 *
244 * @param string $name Constant name.
245 * @param mixed $value Constant value.
246 *
247 * @return void
248 */
249 private function define( string $name, $value ) {
250 if ( ! defined( $name ) ) {
251 define( $name, $value );
252 }
253 }
254
255 /**
256 * Setting the locale for translation availability
257 * @return void
258 * @since 1.0.0
259 */
260 public function set_locale() {
261 add_action( 'init', [ $this, 'load_textdomain' ] );
262 }
263
264 /**
265 * Loading Text Domain on init HOOK
266 * @return void
267 * @since 1.0.0
268 *
269 */
270 public function load_textdomain() {
271 load_plugin_textdomain( 'templately', false, dirname( TEMPLATELY_PLUGIN_BASENAME ) . '/languages' );
272 }
273
274 public function google_login_handler() {
275 // Stop if not a templately google login request
276 if ( empty( $_GET['templately_google_login'] ) ) {
277 return;
278 }
279
280 if ( wp_doing_ajax() || wp_doing_cron() || ( defined( 'REST_REQUEST' ) && REST_REQUEST ) ) {
281 return;
282 }
283
284 // Checked before the token is consumed: the callback can land while the
285 // auth cookie is missing (expired session, cookie not yet set), and WP
286 // will bounce the user through wp-login and back to this same URL.
287 // Burning the token here would fail that legitimate retry.
288 if ( ! is_user_logged_in() ) {
289 return;
290 }
291
292 $state = '';
293 if ( ! empty( $_GET['templately_state'] ) ) {
294 $state = sanitize_text_field( wp_unslash( $_GET['templately_state'] ) );
295 } elseif ( ! empty( $_GET['state'] ) ) {
296 $state = sanitize_text_field( wp_unslash( $_GET['state'] ) );
297 }
298
299 $state_user_id = false;
300 if ( ! empty( $state ) ) {
301 $state_user_id = Database::get_transient( 'google_state_' . $state );
302 Database::delete_transient( 'google_state_' . $state );
303 }
304
305 $is_authorized = false !== $state_user_id
306 && intval( $state_user_id ) === get_current_user_id()
307 && current_user_can( 'delete_posts' );
308
309 $redirect_url = remove_query_arg( [ 'templately_google_login', 'templately_state', 'api_key', 'error', 'state', 'redirect-to' ] );
310
311 if ( ! $is_authorized ) {
312 $error_code = AuthErrorCode::AUTH_STATE_INVALID;
313 } elseif ( ! empty( $_GET['error'] ) ) {
314 // Google's own reason is deliberately dropped rather than forwarded:
315 // everything on this query string is attacker-controlled, and the
316 // screen that displays it must never be handed prose from the URL.
317 $error_code = AuthErrorCode::AUTH_PROVIDER_FAILED;
318 } elseif ( ! empty( $_GET['api_key'] ) ) {
319 $request = new \WP_REST_Request( 'POST', '/templately/v1/login' );
320 $request->set_param( 'viaAPI', true );
321 $request->set_param( 'api_key', sanitize_text_field( $_GET['api_key'] ) );
322
323 /**
324 * @var Login $login
325 */
326 $login = Login::get_instance();
327 $login->permission_check( $request );
328
329 // login() pins the write target to the acting user itself — no pin
330 // here, or its finally would release ours mid-request.
331 $response = $login->login();
332
333 if ( ! is_wp_error( $response ) && ! empty( $response['user'] ) ) {
334 $redirect_path = ! empty( $_GET['redirect-to'] ) ? sanitize_text_field( wp_unslash( $_GET['redirect-to'] ) ) : '';
335 if ( ! empty( $redirect_path ) ) {
336 if ( filter_var( $redirect_path, FILTER_VALIDATE_URL ) ) {
337 $redirect_url = $redirect_path;
338 } else {
339 $is_templately = strpos( $redirect_url, 'page=templately' ) !== false;
340 $is_elementor = strpos( $redirect_url, 'action=elementor' ) !== false;
341 // Gutenberg editor usually has action=edit or is a block editor page
342 $is_gutenberg = ( strpos( $redirect_url, 'action=edit' ) !== false || strpos( $redirect_url, 'post_type=' ) !== false ) && ! $is_elementor;
343
344 if ( $is_templately || $is_elementor || $is_gutenberg ) {
345 $redirect_url = add_query_arg( 'path', ltrim( $redirect_path, '/' ), $redirect_url );
346
347 // Always open the modal in editors after google login
348 if ( $is_elementor || $is_gutenberg ) {
349 $redirect_url = add_query_arg( 'templately_open_modal', '1', $redirect_url );
350 }
351 }
352 }
353 }
354
355 wp_safe_redirect( $redirect_url );
356 exit;
357 } else {
358 // The cloud's own wording stays server-side; the screen resolves
359 // its copy from the code.
360 $error_code = AuthErrorCode::INVALID_API_KEY;
361 }
362 } else {
363 $error_code = AuthErrorCode::AUTH_MISSING_API_KEY;
364 }
365
366 $redirect_url = add_query_arg( [
367 'templately_error' => $error_code,
368 ], $redirect_url );
369
370 wp_safe_redirect( $redirect_url );
371 exit;
372 }
373 }
374