PluginProbe
Code Engine – PHP Snippets, AI Functions & Automation for WordPress / 0.5.6
Code Engine – PHP Snippets, AI Functions & Automation for WordPress v0.5.6
0.5.7 0.5.6 0.5.5 0.5.4 0.5.3 0.5.2 0.5.1 0.5.0 0.4.9 0.4.8 0.4.7 0.4.6 trunk 0.0.1 0.0.2 0.2.8 0.2.9 0.3.0 0.3.1 0.3.2 0.3.3 0.3.4 0.3.5 0.3.6 0.3.7 All 33 releases
← All changes | classes/modules/snippet.php +72 -9 0.3.20.5.6 View file →
@@ -137,20 +137,22 @@
137 137 $snippet['functionArgs'] = [];
138 138 $snippet['functionArgsDict'] = [];
139 139 $snippet['functionBehavior'] = '';
140 140 $snippet['functionTarget'] = 'PHP';
141 + $snippet['functionMcp'] = false;
141 142
142 143 foreach ( $functions_snippet as $function_snippet ) {
143 144 if ( $function_snippet['snippetId'] == $snippetId ) {
144 145
145 146 $snippet['functionName'] = $function_snippet['name'];
146 - if ( !isset( $snippet['functionBehavior'] ) || empty( $snippet['functionBehavior'] ) ) {
147 + $snippet['functionMcp'] = !empty( $function_snippet['mcp'] );
148 + if ( !isset( $function_snippet['behavior'] ) || empty( $function_snippet['behavior'] ) ) {
147 149 $snippet['functionBehavior'] = 'dynamic';
148 150 }
149 151 else {
150 152 $snippet['functionBehavior'] = $function_snippet['behavior'];
151 153 }
152 - if ( !isset( $snippet['functionTarget'] ) || empty( $snippet['functionTarget'] ) ) {
154 + if ( !isset( $function_snippet['target'] ) || empty( $function_snippet['target'] ) ) {
153 155 $snippet['functionTarget'] = 'PHP';
154 156 }
155 157 else {
156 158 $snippet['functionTarget'] = $function_snippet['target'];
@@ -215,8 +217,9 @@
215 217 'name' => $params['functionName'],
216 218 'behavior' => $params['functionBehavior'],
217 219 'desc' => $params['description'] ?? '',
218 220 'target' => $params['functionTarget'] ?? 'PHP',
221 + 'mcp' => !empty( $params['functionMcp'] ),
219 222 'args' => [],
220 223 ];
221 224
222 225 foreach ( $params['functionArgs'] as $argName ) {
@@ -353,8 +356,27 @@
353 356
354 357 return null;
355 358 }
356 359
360 + /**
361 + * Return the snippet IDs of every function that opted in to MCP exposure.
362 + * Used by the "MCP" list filter and its count (functionMcp lives in the
363 + * functions option, not a snippets table column, so it can't be queried in SQL).
364 + *
365 + * @return int[]
366 + */
367 + public function get_mcp_function_ids()
368 + {
369 + $functions = get_option( $this->option_functions, [] );
370 + $ids = [];
371 + foreach ( $functions as $fn ) {
372 + if ( !empty( $fn['mcp'] ) && !empty( $fn['snippetId'] ) ) {
373 + $ids[] = (int) $fn['snippetId'];
374 + }
375 + }
376 + return $ids;
377 + }
378 +
357 379 #endregion
358 380
359 381 #region Utilities
360 382
@@ -390,8 +412,9 @@
390 412 $scopes = [
391 413 "global" => "persistent",
392 414 "front-end" => "frontend",
393 415 "admin" => "backend",
416 + "content" => "content_php",
394 417 ];
395 418
396 419 if ( array_key_exists( $params['scope'], $scopes ) ) {
397 420 $params['scope'] = $scopes[$params['scope']];
@@ -536,9 +559,9 @@
536 559 return $tag !== '';
537 560 } );
538 561 }
539 562 $params['tags'] = $tags ? implode( ',', $tags ) : '';
540 - $params['code'] = $this->sanitize_code( $params['code'] );
563 + //$params['code'] = $this->sanitize_code( $params['code'] );
541 564 return $params;
542 565 }
543 566
544 567 /**
@@ -549,9 +572,9 @@
549 572 */
550 573 private function formatParamsForFront( $params )
551 574 {
552 575 // Separate the scope tags from the tags
553 - $scopes = ['backend', 'frontend', 'function', 'persistent', 'scheduled'];
576 + $scopes = ['backend', 'frontend', 'function', 'persistent', 'scheduled', 'content_php', 'content_js'];
554 577
555 578 if ( isset( $params['tags'] ) && !empty( $params['tags'] ) ) {
556 579
557 580 $tags = array_map( function ( $tag ) use ( $scopes ) {
@@ -585,9 +608,15 @@
585 608 $stats[$scope] = $this->wpdb->get_var( $this->wpdb->prepare( "SELECT COUNT( * ) FROM $this->table_name WHERE scope = %s", $scope ) );
586 609 }
587 610 $stats['all'] += $stats[$scope];
588 611 }
589 -
612 +
613 + // Combined count for the "Content" filter (PHP + JS). Not added to 'all', already counted above.
614 + $stats['content'] = (int) $stats['content_php'] + (int) $stats['content_js'];
615 +
616 + // Functions exposed via MCP. A subset of 'function', so not added to 'all'.
617 + $stats['mcp'] = count( $this->get_mcp_function_ids() );
618 +
590 619 return $stats;
591 620 }
592 621
593 622 public function import( )
@@ -610,15 +639,34 @@
610 639
611 640 return count( $snippets );
612 641 }
613 642
614 - private function sanitize_code( $code )
643 + public function sanitize_code( $code )
615 644 {
616 - $code = preg_replace( '/<\?php/', '', $code, 1 );
617 645 $code = ltrim( $code );
646 +
647 + $first_chats = substr( $code, 0, 5 );
648 + if( $first_chats === '<?php' ) {
649 + $code = substr( $code, 5 );
650 + $code = ltrim( $code );
651 + }
652 +
618 653 return $code;
619 654 }
620 655
656 + public function delete_duplicates() {
657 + // Delete snippets that have the same code and scope, keeping only the most recent one ( based on the updated column )
658 + $query = "DELETE t1 FROM $this->table_name t1
659 + INNER JOIN $this->table_name t2
660 + WHERE t1.id < t2.id
661 + AND t1.code = t2.code
662 + AND t1.scope = t2.scope";
663 +
664 + $this->wpdb->query( $query );
665 +
666 + return $this->wpdb->rows_affected;
667 + }
668 +
621 669 #endregion
622 670
623 671 #region Snippet CRUD
624 672
@@ -649,8 +697,11 @@
649 697 }
650 698 else if ( $filter['accessor'] === 'scope' && $filter['value'] === 'global' ) {
651 699 $freshFilters[] = [ 'accessor' => 'scope', 'value' => ['backend', 'frontend', 'persistent'] ];
652 700 }
701 + else if ( $filter['accessor'] === 'scope' && $filter['value'] === 'content' ) {
702 + $freshFilters[] = [ 'accessor' => 'scope', 'value' => ['content_php', 'content_js'] ];
703 + }
653 704 else {
654 705 $freshFilters[] = $filter;
655 706 }
656 707 }
@@ -682,14 +733,22 @@
682 733 $where[] = $this->wpdb->prepare( "active = %d", $value );
683 734 } elseif ( $filter['accessor'] === 'endpoint' ) {
684 735 $where[] = boolval( $filter['value'] ) ? "endpoint <> ''" : "endpoint = ''";
685 736 } elseif ( $filter['accessor'] === 'scope' ) {
686 - if ( is_array( $filter['value'] ) ) {
737 + if ( $filter['value'] === 'mcp' ) {
738 + // Not a scope: constrain to the functions opted in to MCP exposure.
739 + $ids = $this->get_mcp_function_ids();
740 + if ( empty( $ids ) ) {
741 + $where[] = '1 = 0';
742 + } else {
743 + $where[] = 'id IN (' . implode( ',', array_map( 'intval', $ids ) ) . ')';
744 + }
745 + } else if ( is_array( $filter['value'] ) ) {
687 746 $scopes = array_map( function( $scope ) {
688 747 return esc_sql( $scope );
689 748 }, $filter['value'] );
690 749 $where[] = "scope IN ('" . implode( "', '", $scopes ) . "')";
691 - } else {
750 + } else if ( !empty( $filter['value'] ) ) {
692 751 $value = esc_sql( $filter['value'] );
693 752 $where[] = $this->wpdb->prepare( "scope = %s", $value );
694 753 }
695 754 }
@@ -874,8 +933,12 @@
874 933 }
875 934
876 935 function check_db( )
877 936 {
937 + if ( $this->db_check ) {
938 + return true;
939 + }
940 +
878 941 if ( $this->does_table_exist( $this->table_name ) ) {
879 942 $this->check_columns( );
880 943 $this->db_check = true;
881 944 } else {