PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 5.0
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v5.0
6.35 6.34 6.33.1 6.33 6.32.1 6.32 6.31 6.25 6.25.1 6.26 6.26.1 6.27 6.28 6.29 6.3 6.3.1 6.3.2 6.30 6.4 6.4.1 6.4.2 6.5 6.5.1 6.5.2 6.5.3 All 141 releases
← All changes | classes/models/FrmSolution.php +48 -196 6.265.0 View file →
@@ -3,10 +3,8 @@
3 3 * Handles the installation of a solution and any dependencies.
4 4 * This page is shown when a Formidable plugin is activated.
5 5 *
6 6 * @since 4.06.02
7 - *
8 - * @package Formidable
9 7 */
10 8
11 9 if ( ! defined( 'ABSPATH' ) ) {
12 10 die( 'You are not allowed to call this page directly.' );
@@ -13,16 +11,10 @@
13 11 }
14 12
15 13 class FrmSolution {
16 14
17 - /**
18 - * @var string
19 - */
20 15 protected $plugin_slug = '';
21 16
22 - /**
23 - * @var string
24 - */
25 17 protected $plugin_file = '';
26 18
27 19 /**
28 20 * Hidden welcome page slug.
@@ -27,21 +19,13 @@
27 19 /**
28 20 * Hidden welcome page slug.
29 21 *
30 22 * @since 4.06.02
31 - *
32 - * @var string
33 23 */
34 24 protected $page = '';
35 25
36 - /**
37 - * @var string
38 - */
39 26 protected $icon = 'frm_icon_font frm_settings_icon';
40 27
41 - /**
42 - * @param array $atts
43 - */
44 28 public function __construct( $atts = array() ) {
45 29 if ( empty( $this->plugin_slug ) ) {
46 30 return;
47 31 }
@@ -57,10 +41,8 @@
57 41 /**
58 42 * Register all WP hooks.
59 43 *
60 44 * @since 4.06.02
61 - *
62 - * @return void
63 45 */
64 46 public function load_hooks() {
65 47 // If user is in admin ajax or doing cron, return.
66 48 if ( wp_doing_cron() ) {
@@ -82,13 +64,8 @@
82 64 add_action( 'admin_menu', array( $this, 'register' ) );
83 65 add_action( 'admin_head', array( $this, 'hide_menu' ) );
84 66 }
85 67
86 - /**
87 - * @param array $links
88 - *
89 - * @return array
90 - */
91 68 public function plugin_links( $links ) {
92 69 if ( ! $this->is_complete() ) {
93 70 $settings = '<a href="' . esc_url( $this->settings_link() ) . '">' . __( 'Setup', 'formidable' ) . '</a>';
94 71 array_unshift( $links, $settings );
@@ -103,10 +80,8 @@
103 80 * These pages will be removed from the Dashboard menu, so they will
104 81 * not actually show. Sneaky, sneaky.
105 82 *
106 83 * @since 4.06.02
107 - *
108 - * @return void
109 84 */
110 85 public function register() {
111 86
112 87 // Getting started - shows after installation.
@@ -124,34 +99,21 @@
124 99 *
125 100 * This means the pages are still available to us, but hidden.
126 101 *
127 102 * @since 4.06.02
128 - *
129 - * @return void
130 103 */
131 104 public function hide_menu() {
132 105 remove_submenu_page( 'index.php', $this->page );
133 106 }
134 107
135 - /**
136 - * @return string
137 - *
138 - * @psalm-return ''
139 - */
140 108 protected function plugin_name() {
141 109 return '';
142 110 }
143 111
144 - /**
145 - * @return string
146 - */
147 112 protected function page_title() {
148 113 return __( 'Welcome to Formidable Forms', 'formidable' );
149 114 }
150 115
151 - /**
152 - * @return string
153 - */
154 116 protected function page_description() {
155 117 return __( 'Follow the steps below to get started.', 'formidable' );
156 118 }
157 119
@@ -161,15 +123,12 @@
161 123 * This function checks if a new install or update has just occurred. If so,
162 124 * then we redirect the user to the appropriate page.
163 125 *
164 126 * @since 4.06.02
165 - *
166 - * @return void
167 127 */
168 128 public function redirect() {
169 129
170 130 $current_page = FrmAppHelper::simple_get( 'page', 'sanitize_title' );
171 -
172 131 if ( $current_page === $this->page ) {
173 132 // Prevent endless loop.
174 133 return;
175 134 }
@@ -174,9 +133,9 @@
174 133 return;
175 134 }
176 135
177 136 // Only do this for single site installs.
178 - if ( isset( $_GET['activate-multi'] ) || is_network_admin() ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
137 + if ( isset( $_GET['activate-multi'] ) || is_network_admin() ) { // WPCS: CSRF ok.
179 138 return;
180 139 }
181 140
182 141 // Check if we should consider redirection.
@@ -183,9 +142,9 @@
183 142 if ( ! $this->is_current_plugin() ) {
184 143 return;
185 144 }
186 145
187 - delete_transient( FrmOnboardingWizardController::TRANSIENT_NAME );
146 + delete_transient( 'frm_activation_redirect' );
188 147
189 148 // Initial install.
190 149 wp_safe_redirect( $this->settings_link() );
191 150 exit;
@@ -190,21 +149,14 @@
190 149 wp_safe_redirect( $this->settings_link() );
191 150 exit;
192 151 }
193 152
194 - /**
195 - * @return string
196 - */
197 153 protected function settings_link() {
198 154 return admin_url( 'index.php?page=' . $this->page );
199 155 }
200 156
201 - /**
157 + /*
202 158 * Add page to global settings.
203 - *
204 - * @param array $sections Sections.
205 - *
206 - * @return array
207 159 */
208 160 public function add_settings( $sections ) {
209 161 wp_enqueue_style( 'formidable-pro-fields' );
210 162 $sections[ $this->plugin_slug ] = array(
@@ -219,14 +171,10 @@
219 171
220 172 /*
221 173 * Output for global settings.
222 174 */
223 - /**
224 - * @return void
225 - */
226 175 public function settings_page() {
227 176 $steps = $this->get_steps_data();
228 -
229 177 if ( ! $steps['license']['complete'] || ( isset( $steps['plugin'] ) && ! $steps['plugin']['complete'] ) ) {
230 178 // Redirect to the welcome page if install hasn't been done.
231 179 $url = $this->settings_link();
232 180 echo '<script>window.location.replace("' . esc_url_raw( $url ) . '");</script>';
@@ -242,12 +190,11 @@
242 190 if ( $steps['complete']['current'] ) {
243 191 // Always show this step in settings.
244 192 $step['current'] = true;
245 193
246 - $new_class = $all_imported ? ' button frm_hidden' : '';
194 + $new_class = $all_imported ? ' button frm_hidden' : '';
247 195 $step['button_class'] = str_replace( 'frm_grey disabled', $new_class, $step['button_class'] );
248 196 }
249 -
250 197 if ( $all_imported ) {
251 198 $step['description'] = __( 'The following form(s) have been created.', 'formidable' );
252 199 }
253 200 $this->show_app_install( $step );
@@ -252,10 +199,10 @@
252 199 }
253 200 $this->show_app_install( $step );
254 201
255 202 if ( ! $all_imported ) {
256 - $step = $steps['complete'];
257 - $step['current'] = false;
203 + $step = $steps['complete'];
204 + $step['current'] = false;
258 205 $step['button_class'] .= ' frm_grey disabled';
259 206 $this->show_page_links( $step );
260 207 }
261 208 }
@@ -261,10 +208,8 @@
261 208 }
262 209
263 210 /**
264 211 * Getting Started screen. Shows after first install.
265 - *
266 - * @return void
267 212 */
268 213 public function output() {
269 214 FrmAppHelper::include_svg();
270 215 $this->css();
@@ -279,10 +224,8 @@
279 224 }
280 225
281 226 /**
282 227 * Heading section.
283 - *
284 - * @return void
285 228 */
286 229 protected function header() {
287 230 $size = array(
288 231 'height' => 90,
@@ -318,15 +261,12 @@
318 261
319 262 /**
320 263 * This is the welcome page content.
321 264 * Override me to insert different content.
322 - *
323 - * @return void
324 265 */
325 266 protected function main_content() {
326 267 $steps = $this->get_steps_data();
327 268 $this->license_box( $steps['license'] );
328 -
329 269 if ( isset( $steps['plugin'] ) ) {
330 270 $this->show_plugin_install( $steps['plugin'] );
331 271 }
332 272 $this->show_app_install( $steps['import'] );
@@ -332,44 +272,41 @@
332 272 $this->show_app_install( $steps['import'] );
333 273 $this->show_page_links( $steps['complete'] );
334 274 }
335 275
336 - /**
337 - * @return array
338 - */
339 276 protected function get_steps_data() {
340 277 $pro_installed = FrmAppHelper::pro_is_connected();
341 278
342 279 $steps = array(
343 - 'license' => array(
344 - 'label' => __( 'Connect to FormidableForms.com', 'formidable' ),
345 - 'description' => __( 'Create a connection to get plugin downloads.', 'formidable' ),
346 - 'button_label' => __( 'Connect an Account', 'formidable' ),
347 - 'current' => empty( $pro_installed ),
348 - 'complete' => $pro_installed,
349 - 'num' => 1,
280 + 'license' => array(
281 + 'label' => __( 'Connect to FormidableForms.com', 'formidable' ),
282 + 'description' => __( 'Create a connection to get plugin downloads.', 'formidable' ),
283 + 'button_label' => __( 'Connect an Account', 'formidable' ),
284 + 'current' => empty( $pro_installed ),
285 + 'complete' => $pro_installed,
286 + 'num' => 1,
350 287 ),
351 - 'plugin' => array(
352 - 'label' => __( 'Install and Activate Add-Ons', 'formidable' ),
353 - 'description' => __( 'Install any required add-ons from FormidableForms.com.', 'formidable' ),
354 - 'button_label' => __( 'Install & Activate', 'formidable' ),
355 - 'current' => false,
356 - 'complete' => false,
357 - 'num' => 2,
288 + 'plugin' => array(
289 + 'label' => __( 'Install and Activate Add-Ons', 'formidable' ),
290 + 'description' => __( 'Install any required add-ons from FormidableForms.com.', 'formidable' ),
291 + 'button_label' => __( 'Install & Activate', 'formidable' ),
292 + 'current' => false,
293 + 'complete' => false,
294 + 'num' => 2,
358 295 ),
359 - 'import' => array(
360 - 'label' => __( 'Setup Forms, Views, and Pages', 'formidable' ),
361 - 'description' => __( 'Build the forms, views, and pages automatically.', 'formidable' ),
362 - 'button_label' => __( 'Create Now', 'formidable' ),
363 - 'complete' => $this->is_complete(),
364 - 'num' => 3,
296 + 'import' => array(
297 + 'label' => __( 'Setup Forms, Views, and Pages', 'formidable' ),
298 + 'description' => __( 'Build the forms, views, and pages automatically.', 'formidable' ),
299 + 'button_label' => __( 'Create Now', 'formidable' ),
300 + 'complete' => $this->is_complete(),
301 + 'num' => 3,
365 302 ),
366 303 'complete' => array(
367 - 'label' => __( 'Customize Your New Pages', 'formidable' ),
368 - 'description' => __( 'Make any required changes and publish the page.', 'formidable' ),
369 - 'button_label' => __( 'View Page', 'formidable' ),
370 - 'complete' => false,
371 - 'num' => 4,
304 + 'label' => __( 'Customize Your New Pages', 'formidable' ),
305 + 'description' => __( 'Make any required changes and publish the page.', 'formidable' ),
306 + 'button_label' => __( 'View Page', 'formidable' ),
307 + 'complete' => false,
308 + 'num' => 4,
372 309 ),
373 310 );
374 311
375 312 $this->adjust_plugin_install_step( $steps );
@@ -374,9 +311,8 @@
374 311
375 312 $this->adjust_plugin_install_step( $steps );
376 313
377 314 $has_current = false;
378 -
379 315 foreach ( $steps as $k => $step ) {
380 316 // Set the current step.
381 317 if ( ! isset( $step['current'] ) ) {
382 318 if ( $step['complete'] ) {
@@ -382,9 +318,9 @@
382 318 if ( $step['complete'] ) {
383 319 $steps[ $k ]['current'] = false;
384 320 } else {
385 321 $steps[ $k ]['current'] = ! $has_current;
386 - $has_current = true;
322 + $has_current = true;
387 323 }
388 324 } elseif ( $step['current'] ) {
389 325 $has_current = true;
390 326 }
@@ -389,28 +325,21 @@
389 325 $has_current = true;
390 326 }
391 327
392 328 // Set disabled buttons.
393 - $class = $step['button_class'] ?? '';
329 + $class = isset( $step['button_class'] ) ? $step['button_class'] : '';
394 330 $class .= ' button-primary frm-button-primary';
395 -
396 331 if ( ! $steps[ $k ]['current'] ) {
397 332 $class .= ' frm_grey disabled';
398 333 }
399 334 $steps[ $k ]['button_class'] = $class;
400 - }//end foreach
335 + }
401 336
402 337 return $steps;
403 338 }
404 339
405 - /**
406 - * @param array $steps
407 - *
408 - * @return void
409 - */
410 340 protected function adjust_plugin_install_step( &$steps ) {
411 341 $plugins = $this->required_plugins();
412 -
413 342 if ( empty( $plugins ) ) {
414 343 unset( $steps['plugin'] );
415 344 $steps['import']['num'] = 2;
416 345 $steps['complete']['num'] = 3;
@@ -418,16 +347,14 @@
418 347 }
419 348
420 349 $missing = array();
421 350 $rel = array();
422 -
423 351 foreach ( $plugins as $plugin_key ) {
424 352 $plugin = FrmAddonsController::install_link( $plugin_key );
425 -
426 353 if ( $plugin['status'] === 'active' ) {
427 354 continue;
428 355 }
429 -
356 + $links[ $plugin_key ] = $plugin;
430 357 if ( isset( $plugin['url'] ) ) {
431 358 $rel[] = $plugin['url'];
432 359 } else {
433 360 // Add-on is required but not allowed.
@@ -433,9 +360,8 @@
433 360 // Add-on is required but not allowed.
434 361 $missing[] = $plugin_key;
435 362 }
436 363 }
437 -
438 364 if ( empty( $rel ) && empty( $missing ) ) {
439 365 $steps['plugin']['complete'] = true;
440 366 } elseif ( ! empty( $missing ) ) {
441 367 $steps['plugin']['error'] = sprintf(
@@ -443,9 +369,9 @@
443 369 esc_html__( 'You need permission to download the Formidable %1$s plugin', 'formidable' ),
444 370 implode( ', ', $missing )
445 371 );
446 372 } else {
447 - $steps['plugin']['links'] = $rel;
373 + $steps['plugin']['links'] = $rel;
448 374 $steps['plugin']['button_class'] = 'frm-solution-multiple ';
449 375 }
450 376
451 377 if ( $steps['license']['complete'] && ! $steps['plugin']['complete'] ) {
@@ -452,15 +378,10 @@
452 378 $steps['plugin']['current'] = true;
453 379 }
454 380 }
455 381
456 - /**
457 - * @param array $step Step.
458 - *
459 - * @return void
460 - */
461 382 protected function step_top( $step ) {
462 - $section_class = empty( $step['current'] ) ? 'frm_grey' : '';
383 + $section_class = ( ! isset( $step['current'] ) || ! $step['current'] ) ? 'frm_grey' : '';
463 384
464 385 ?>
465 386 <section class="step step-install <?php echo esc_attr( $section_class ); ?>">
466 387 <aside class="num">
@@ -492,13 +413,8 @@
492 413 <?php } ?>
493 414 <?php
494 415 }
495 416
496 - /**
497 - * @param array $step Step.
498 - *
499 - * @return void
500 - */
501 417 protected function step_bottom( $step ) {
502 418 ?>
503 419 </div>
504 420 </section>
@@ -506,12 +422,8 @@
506 422 }
507 423
508 424 /**
509 425 * Generate and output Connect step section HTML.
510 - *
511 - * @param array $step Step.
512 - *
513 - * @return void
514 426 */
515 427 protected function license_box( $step ) {
516 428 $this->step_top( $step );
517 429
@@ -527,18 +439,13 @@
527 439
528 440 $this->step_bottom( $step );
529 441 }
530 442
531 - /**
532 - * @param array $step Step.
533 - *
534 - * @return void
535 - */
536 443 protected function show_plugin_install( $step ) {
537 444 $this->step_top( $step );
538 445
539 446 if ( ! isset( $step['error'] ) ) {
540 - $rel = $step['links'] ?? array();
447 + $rel = isset( $step['links'] ) ? $step['links'] : array();
541 448
542 449 ?>
543 450 <a rel="<?php echo esc_attr( implode( ',', $rel ) ); ?>" class="<?php echo esc_attr( $step['button_class'] ); ?>">
544 451 <?php echo esc_html( $step['button_label'] ); ?>
@@ -548,16 +455,10 @@
548 455
549 456 $this->step_bottom( $step );
550 457 }
551 458
552 - /**
553 - * @param array $step Step.
554 - *
555 - * @return void
556 - */
557 459 protected function show_app_install( $step ) {
558 460 $is_complete = $step['complete'];
559 -
560 461 if ( ! empty( $this->form_options() ) && ! $is_complete ) {
561 462 $step['description'] = __( 'Select the form or view you would like to create.', 'formidable' );
562 463 }
563 464
@@ -565,9 +466,9 @@
565 466
566 467 $api = new FrmFormApi();
567 468 $addons = $api->get_api_info();
568 469
569 - $id = $this->download_id();
470 + $id = $this->download_id();
570 471 $has_file = isset( $addons[ $id ] ) && isset( $addons[ $id ]['beta'] );
571 472
572 473 if ( ! $step['current'] ) {
573 474 ?>
@@ -585,9 +486,8 @@
585 486 } elseif ( ! isset( $addons[ $id ]['beta']['package'] ) ) {
586 487 echo '<p class="frm_error_style">' . esc_html__( 'Looks like you may not have a current subscription for this solution. Please check your account.', 'formidable' ) . '</p>';
587 488 } else {
588 489 $xml = $addons[ $id ]['beta']['package'];
589 -
590 490 if ( is_array( $xml ) ) {
591 491 $xml = reset( $xml );
592 492 }
593 493
@@ -624,38 +524,21 @@
624 524 echo '</fieldset>';
625 525 } else {
626 526 echo '</form>';
627 527 }
628 - }//end if
528 + }
629 529
630 530 $this->step_bottom( $step );
631 531 }
632 532
633 - /**
634 - * @param string $xml
635 - *
636 - * @return void
637 - */
638 533 protected function show_form_options( $xml ) {
639 534 $this->show_import_options( $this->form_options(), 'form', $xml );
640 535 }
641 536
642 - /**
643 - * @return void
644 - */
645 537 protected function show_view_options() {
646 538 $this->show_import_options( $this->view_options(), 'view' );
647 539 }
648 540
649 - /**
650 - * @param array $options
651 - * @param string $importing
652 - * @param string $xml
653 - *
654 - * @psalm-param 'form'|'view' $importing
655 - *
656 - * @return void
657 - */
658 541 protected function show_import_options( $options, $importing, $xml = '' ) {
659 542 if ( empty( $options ) ) {
660 543 return;
661 544 }
@@ -661,36 +544,29 @@
661 544 }
662 545
663 546 $imported = $this->previously_imported_forms();
664 547 $count = count( $options );
665 -
666 548 foreach ( $options as $info ) {
667 549 // Count the number of options displayed for css.
668 550 if ( $count > 1 && ! isset( $info['img'] ) ) {
669 - --$count;
551 + $count --;
670 552 }
671 553 }
672 -
673 554 $width = floor( ( 533 - ( ( $count - 1 ) * 20 ) ) / $count );
674 555 unset( $count );
675 556
676 557 $selected = false;
677 558
678 - include FrmAppHelper::plugin_path() . '/classes/views/solutions/_import.php';
559 + include( FrmAppHelper::plugin_path() . '/classes/views/solutions/_import.php' );
679 560 }
680 561
681 - /**
682 - * @return void
683 - */
684 562 protected function show_page_options() {
685 563 $pages = $this->needed_pages();
686 -
687 564 if ( empty( $pages ) ) {
688 565 return;
689 566 }
690 567
691 568 echo '<h3>Choose New Page Title</h3>';
692 -
693 569 foreach ( $pages as $page ) {
694 570 ?>
695 571 <p>
696 572 <label for="pages_<?php echo esc_html( $page['type'] ); ?>">
@@ -701,13 +577,8 @@
701 577 <?php
702 578 }
703 579 }
704 580
705 - /**
706 - * @param array $step
707 - *
708 - * @return void
709 - */
710 581 protected function show_page_links( $step ) {
711 582 if ( $step['current'] ) {
712 583 return;
713 584 }
@@ -724,28 +595,19 @@
724 595 }
725 596
726 597 /**
727 598 * Only show the content for the correct plugin.
728 - *
729 - * @return bool
730 599 */
731 600 protected function is_current_plugin() {
732 - $to_redirect = get_transient( FrmOnboardingWizardController::TRANSIENT_NAME );
601 + $to_redirect = get_transient( 'frm_activation_redirect' );
733 602 return $to_redirect === $this->plugin_slug && empty( $this->is_complete() );
734 603 }
735 604
736 605 /**
737 606 * Override this function to indicate when install is complete.
738 - *
739 - * @param int|string $count
740 - *
741 - * @psalm-param 'all'|1 $count
742 - *
743 - * @return bool
744 607 */
745 608 protected function is_complete( $count = 1 ) {
746 609 $imported = $this->previously_imported_forms();
747 -
748 610 if ( $count === 'all' ) {
749 611 return count( $imported ) >= count( $this->form_options() );
750 612 }
751 613 return ! empty( $imported );
@@ -758,12 +620,10 @@
758 620 */
759 621 protected function previously_imported_forms() {
760 622 $imported = array();
761 623 $forms = $this->form_options();
762 -
763 624 foreach ( $forms as $form ) {
764 625 $was_imported = isset( $form['form'] ) ? FrmForm::get_id_by_key( $form['form'] ) : false;
765 -
766 626 if ( $was_imported ) {
767 627 $imported[ $form['form'] ] = $was_imported;
768 628 }
769 629 }
@@ -772,10 +632,8 @@
772 632 }
773 633
774 634 /**
775 635 * In the new plugin has any dependencies, include them here.
776 - *
777 - * @return array
778 636 */
779 637 protected function required_plugins() {
780 638 return array();
781 639 }
@@ -781,10 +639,8 @@
781 639 }
782 640
783 641 /**
784 642 * This needs to be overridden.
785 - *
786 - * @return int
787 643 */
788 644 protected function download_id() {
789 645 return 0;
790 646 }
@@ -790,10 +646,8 @@
790 646 }
791 647
792 648 /**
793 649 * Give options for which forms to import.
794 - *
795 - * @return array
796 650 */
797 651 protected function form_options() {
798 652 /**
799 653 * Example:
@@ -809,10 +663,8 @@
809 663 }
810 664
811 665 /**
812 666 * Give options for which view to use.
813 - *
814 - * @return array
815 667 */
816 668 protected function view_options() {
817 669 return array();
818 670 }
@@ -818,10 +670,8 @@
818 670 }
819 671
820 672 /**
821 673 * If the pages aren't imported automatically, set the page names.
822 - *
823 - * @return array
824 674 */
825 675 protected function needed_pages() {
826 676 /**
827 677 * Example:
@@ -836,16 +686,15 @@
836 686
837 687 return array();
838 688 }
839 689
840 - /**
841 - * @return void
842 - */
843 690 private function css() {
844 691 wp_enqueue_style( 'formidable-pro-fields' );
845 692 ?>
846 693 <style>
847 694 #frm-welcome *, #frm-welcome *::before, #frm-welcome *::after {
695 + -webkit-box-sizing: border-box;
696 + -moz-box-sizing: border-box;
848 697 box-sizing: border-box;
849 698 }
850 699 #frm-welcome{
851 700 width: 700px;
@@ -904,8 +753,10 @@
904 753 border-radius: 3px;
905 754 }
906 755 #frm-welcome .step,
907 756 #frm-welcome .screenshot .cont {
757 + -webkit-box-shadow: 0px 2px 5px 0px rgba(0, 0, 0, 0.05);
758 + -moz-box-shadow: 0px 2px 5px 0px rgba(0, 0, 0, 0.05);
908 759 box-shadow: 0px 2px 5px 0px rgba(0, 0, 0, 0.05);
909 760 }
910 761 #frm-welcome .step {
911 762 background-color: #F9F9F9;
@@ -948,5 +799,6 @@
948 799 }
949 800 </style>
950 801 <?php
951 802 }
803 +
952 804 }