414
414
< div class ="controls ">
415
415
< h1 > WordPress PHP Playground</ h1 >
416
416
< div class ="controls-right ">
417
+ < label for ="wpVersion "> WordPress</ label >
418
+ < select id ="wpVersion ">
419
+ < option > Loading...</ option >
420
+ </ select >
417
421
< label for ="phpVersion "> PHP</ label >
418
422
< select id ="phpVersion ">
419
423
< option value ="8.4 " selected > 8.4</ option >
@@ -478,7 +482,8 @@ <h2>💡 Tips</h2>
478
482
< strong > 🔗 Embed in your app:</ strong > You can embed
479
483
this playground in an iframe to provide interactive
480
484
PHP code snippets. Provide your base64-encoded code
481
- snippet and your PHP version in the URL fragment:
485
+ snippet, PHP version, and WordPress version in the
486
+ URL fragment:
482
487
< pre
483
488
style ="
484
489
background: #f5f5f5;
@@ -512,7 +517,7 @@ <h2>💡 Tips</h2>
512
517
</ div >
513
518
514
519
< script >
515
- // Function to restore code and PHP version from URL fragment
520
+ // Function to restore code, PHP version, and WordPress version from URL fragment
516
521
function loadStateFromURL ( ) {
517
522
const fragment = window . location . hash . slice ( 1 ) ; // Remove #
518
523
if ( fragment ) {
@@ -523,31 +528,33 @@ <h2>💡 Tips</h2>
523
528
return {
524
529
code : state . code || null ,
525
530
phpVersion : state . php || null ,
531
+ wpVersion : state . wp || null ,
526
532
} ;
527
533
} catch ( e ) {
528
534
// Try legacy format (just code)
529
535
return {
530
536
code : decoded ,
531
537
phpVersion : null ,
538
+ wpVersion : null ,
532
539
} ;
533
540
}
534
541
}
535
542
}
536
- return { code : null , phpVersion : null } ;
543
+ return { code : null , phpVersion : null , wpVersion : null } ;
537
544
}
538
545
539
546
/**
540
547
* URL Fragment State Storage
541
548
*
542
- * This implementation stores and restores PHP code and PHP version from the URL fragment using base64 encoding.
549
+ * This implementation stores and restores PHP code, PHP version, and WordPress version from the URL fragment using base64 encoding.
543
550
* Features:
544
551
* - UTF-8 safe encoding/decoding
545
- * - Stores both code and PHP version
552
+ * - Stores code, PHP version, and WordPress version
546
553
* - Automatic saving on code changes (debounced to 500ms)
547
- * - Automatic saving when PHP version changes
554
+ * - Automatic saving when PHP or WordPress version changes
548
555
* - Immediate saving when running code (Cmd+S)
549
556
* - Browser navigation support (back/forward buttons)
550
- * - Shareable URLs with embedded code and PHP version
557
+ * - Shareable URLs with embedded code and versions
551
558
* - Backward compatibility with legacy code-only URLs
552
559
*/
553
560
@@ -589,25 +596,33 @@ <h2>💡 Tips</h2>
589
596
}
590
597
}
591
598
592
- // Function to save code and PHP version to URL fragment
593
- function saveStateToURL ( code , phpVersion ) {
599
+ // Function to save code, PHP version, and WordPress version to URL fragment
600
+ function saveStateToURL ( code , phpVersion , wpVersion ) {
594
601
const state = JSON . stringify ( {
595
602
code : code ,
596
603
php : phpVersion ,
604
+ wp : wpVersion ,
597
605
} ) ;
598
606
const encoded = encodeBase64UTF8 ( state ) ;
599
607
// Use replaceState to avoid adding to browser history
600
608
window . history . replaceState ( null , null , '#' + encoded ) ;
601
609
}
602
610
603
- var versionSelect = document . getElementById ( 'phpVersion' ) ;
611
+ var phpVersionSelect = document . getElementById ( 'phpVersion' ) ;
612
+ var wpVersionSelect = document . getElementById ( 'wpVersion' ) ;
604
613
605
- function restorePHPVersionFromURL ( ) {
614
+ function restoreVersionsFromURL ( ) {
606
615
var defaultPhpVersion = '8.4' ;
607
- const { phpVersion : initialPhpVersion } = loadStateFromURL ( ) ;
608
- versionSelect . value = initialPhpVersion || defaultPhpVersion ;
616
+ var defaultWpVersion = '6.8' ; // Will be updated with actual latest version
617
+ const {
618
+ phpVersion : initialPhpVersion ,
619
+ wpVersion : initialWpVersion ,
620
+ } = loadStateFromURL ( ) ;
621
+ phpVersionSelect . value = initialPhpVersion || defaultPhpVersion ;
622
+ if ( initialWpVersion && wpVersionSelect . options . length > 1 ) {
623
+ wpVersionSelect . value = initialWpVersion ;
624
+ }
609
625
}
610
- restorePHPVersionFromURL ( ) ;
611
626
612
627
// Modal functionality
613
628
const helpBtn = document . getElementById ( 'helpBtn' ) ;
@@ -692,26 +707,32 @@ <h2>💡 Tips</h2>
692
707
import {
693
708
startPlaygroundWeb ,
694
709
SupportedPHPVersionsList ,
695
- } from 'https://esm.sh/@wp-playground/ client' ;
710
+ } from 'https://playground.wordpress.net/ client/index.js ' ;
696
711
697
712
const editorEl = document . getElementById ( 'editor' ) ;
698
713
const phpCompartment = new Compartment ( ) ;
699
714
700
715
const defaultPhpVersion = '8.4' ;
701
- const { phpVersion : initialPhpVersion } = loadStateFromURL ( ) ;
716
+ const {
717
+ phpVersion : initialPhpVersion ,
718
+ wpVersion : initialWpVersion ,
719
+ } = loadStateFromURL ( ) ;
702
720
const startingPhpVersion = initialPhpVersion || defaultPhpVersion ;
703
- // Populate PHP version select options from SupportedPHPVersionsList
704
- versionSelect . innerHTML = '' ; // Clear existing options
721
+ const startingWpVersion = initialWpVersion || 'latest' ;
705
722
723
+ // Populate PHP version select options from SupportedPHPVersionsList
724
+ phpVersionSelect . innerHTML = '' ; // Clear existing options
706
725
SupportedPHPVersionsList . forEach ( ( version ) => {
707
726
const option = document . createElement ( 'option' ) ;
708
727
option . value = version ;
709
728
option . textContent = version ;
710
- versionSelect . appendChild ( option ) ;
729
+ phpVersionSelect . appendChild ( option ) ;
711
730
} ) ;
712
731
713
- // Set the first version as selected by default
714
- restorePHPVersionFromURL ( ) ;
732
+ // WordPress versions will be populated after the client connects
733
+
734
+ // Set the versions from URL or defaults
735
+ restoreVersionsFromURL ( ) ;
715
736
716
737
const defaultCode = `<?php
717
738
echo "Hello from PHP " . phpversion();
@@ -720,6 +741,8 @@ <h2>💡 Tips</h2>
720
741
// WordPress is available if you need it!
721
742
require '/wordpress/wp-load.php';
722
743
744
+ echo "WordPress " . wp_get_wp_version() . "<br>";
745
+
723
746
$html_processor = WP_HTML_Processor::create_fragment('<p><span>Hey!</span></p>');
724
747
$html_processor->next_tag();
725
748
var_dump($html_processor->get_tag());
@@ -761,12 +784,12 @@ <h2>💡 Tips</h2>
761
784
EditorView . updateListener . of ( ( update ) => {
762
785
if ( update . docChanged ) {
763
786
const code = update . state . doc . toString ( ) ;
764
- const phpVersion =
765
- document . getElementById ( 'phpVersion' ) . value ;
787
+ const phpVersion = phpVersionSelect . value ;
788
+ const wpVersion = wpVersionSelect . value ;
766
789
// Debounce URL updates to avoid excessive history updates
767
790
clearTimeout ( window . saveCodeTimeout ) ;
768
791
window . saveCodeTimeout = setTimeout ( ( ) => {
769
- saveStateToURL ( code , phpVersion ) ;
792
+ saveStateToURL ( code , phpVersion , wpVersion ) ;
770
793
} , 500 ) ;
771
794
}
772
795
} ) ,
@@ -797,56 +820,95 @@ <h2>💡 Tips</h2>
797
820
const runBtn = document . getElementById ( 'runBtn' ) ;
798
821
const previewIframe = document . getElementById ( 'preview' ) ;
799
822
800
- // Set initial PHP version from URL
823
+ // Set initial versions from URL
801
824
if ( startingPhpVersion ) {
802
- versionSelect . value = startingPhpVersion ;
825
+ phpVersionSelect . value = startingPhpVersion ;
826
+ }
827
+ if ( startingWpVersion && wpVersionSelect . options . length > 1 ) {
828
+ wpVersionSelect . value = startingWpVersion ;
803
829
}
804
830
805
831
let client = null ;
806
- let currentPhpVersion = versionSelect . value ;
832
+ let currentPhpVersion = phpVersionSelect . value ;
833
+ let currentWpVersion = wpVersionSelect . value ;
807
834
808
835
// Detect platform for keyboard shortcut display
809
836
const isMac = navigator . platform . toUpperCase ( ) . indexOf ( 'MAC' ) >= 0 ;
810
837
const shortcutText = isMac ? 'Cmd+S' : 'Ctrl+S' ;
811
838
runBtn . textContent = `Run (${ shortcutText } )` ;
812
839
813
840
// Save to URL when PHP version changes
814
- versionSelect . addEventListener ( 'change' , ( ) => {
841
+ phpVersionSelect . addEventListener ( 'change' , ( ) => {
815
842
const code = view . state . doc . toString ( ) ;
816
- const phpVersion = versionSelect . value ;
817
- saveStateToURL ( code , phpVersion ) ;
843
+ const phpVersion = phpVersionSelect . value ;
844
+ const wpVersion = wpVersionSelect . value ;
845
+ saveStateToURL ( code , phpVersion , wpVersion ) ;
818
846
} ) ;
819
847
820
- async function bootPlayground ( version ) {
821
- // Point the iframe at the appropriate PHP version using the Query API
822
- previewIframe . src = `https://playground.wordpress.net/remote.html?php=${ encodeURIComponent (
823
- version
824
- ) } `;
848
+ // Save to URL when WordPress version changes
849
+ wpVersionSelect . addEventListener ( 'change' , ( ) => {
850
+ const code = view . state . doc . toString ( ) ;
851
+ const phpVersion = phpVersionSelect . value ;
852
+ const wpVersion = wpVersionSelect . value ;
853
+ saveStateToURL ( code , phpVersion , wpVersion ) ;
854
+ } ) ;
855
+
856
+ async function bootPlayground ( phpVersion , wpVersion ) {
857
+ // Point the iframe at the appropriate PHP and WordPress versions using the Query API
858
+ previewIframe . src = `https://playground.wordpress.net/remote.html` ;
825
859
client = await startPlaygroundWeb ( {
826
860
iframe : previewIframe ,
827
861
remoteUrl : previewIframe . src ,
828
862
blueprint : {
829
863
preferredVersions : {
830
- wp : 'latest' ,
831
- php : version ,
864
+ wp : wpVersion ,
865
+ php : phpVersion ,
832
866
} ,
833
867
} ,
834
868
} ) ;
869
+
870
+ // Populate WordPress versions from the connected client
871
+ try {
872
+ const { all, latest } =
873
+ await client . getMinifiedWordPressVersions ( ) ;
874
+ const keys = Object . keys ( all ) ;
875
+ wpVersionSelect . innerHTML = '' ;
876
+ for ( const version of keys ) {
877
+ const option = document . createElement ( 'option' ) ;
878
+ option . value = version ;
879
+ option . textContent = version ;
880
+ wpVersionSelect . appendChild ( option ) ;
881
+ }
882
+ // Restore selection if still available; otherwise fall back to latest
883
+ wpVersionSelect . value = keys . includes ( startingWpVersion )
884
+ ? startingWpVersion
885
+ : latest ;
886
+ } catch ( e ) {
887
+ console . warn (
888
+ 'Failed to load WordPress versions list from client' ,
889
+ e
890
+ ) ;
891
+ }
835
892
await client . isReady ;
836
893
await client . writeFile ( '/wordpress/code.php' , startingCode ) ;
837
894
await client . goTo ( '/code.php' ) ; // Blank document
838
895
}
839
896
840
897
async function executeCode ( ) {
841
898
const code = view . state . doc . toString ( ) ;
842
- const phpVersion = versionSelect . value ;
899
+ const phpVersion = phpVersionSelect . value ;
900
+ const wpVersion = wpVersionSelect . value ;
843
901
844
- // Save code and PHP version to URL fragment immediately when running
845
- saveStateToURL ( code , phpVersion ) ;
902
+ // Save code, PHP version, and WordPress version to URL fragment immediately when running
903
+ saveStateToURL ( code , phpVersion , wpVersion ) ;
846
904
847
- if ( phpVersion !== currentPhpVersion ) {
905
+ if (
906
+ phpVersion !== currentPhpVersion ||
907
+ wpVersion !== currentWpVersion
908
+ ) {
848
909
currentPhpVersion = phpVersion ;
849
- await bootPlayground ( currentPhpVersion ) ;
910
+ currentWpVersion = wpVersion ;
911
+ await bootPlayground ( currentPhpVersion , currentWpVersion ) ;
850
912
}
851
913
await client . writeFile ( '/wordpress/code.php' , code ) ;
852
914
const uuid = crypto . randomUUID ( ) ;
@@ -857,8 +919,11 @@ <h2>💡 Tips</h2>
857
919
858
920
// Handle browser navigation (back/forward) to restore code from URL
859
921
window . addEventListener ( 'hashchange' , ( ) => {
860
- const { code : codeFromURL , phpVersion : phpVersionFromURL } =
861
- loadStateFromURL ( ) ;
922
+ const {
923
+ code : codeFromURL ,
924
+ phpVersion : phpVersionFromURL ,
925
+ wpVersion : wpVersionFromURL ,
926
+ } = loadStateFromURL ( ) ;
862
927
863
928
if ( codeFromURL !== null ) {
864
929
const currentCode = view . state . doc . toString ( ) ;
@@ -876,20 +941,32 @@ <h2>💡 Tips</h2>
876
941
877
942
if (
878
943
phpVersionFromURL !== null &&
879
- phpVersionFromURL !== versionSelect . value
944
+ phpVersionFromURL !== phpVersionSelect . value
880
945
) {
881
946
// Update PHP version selector
882
- versionSelect . value = phpVersionFromURL ;
947
+ phpVersionSelect . value = phpVersionFromURL ;
948
+ }
949
+
950
+ if (
951
+ wpVersionFromURL !== null &&
952
+ wpVersionFromURL !== wpVersionSelect . value
953
+ ) {
954
+ // Update WordPress version selector
955
+ wpVersionSelect . value = wpVersionFromURL ;
883
956
}
884
957
} ) ;
885
958
886
959
// Save initial state to URL if not already present
887
960
if ( ! window . location . hash ) {
888
- saveStateToURL ( startingCode , startingPhpVersion ) ;
961
+ saveStateToURL (
962
+ startingCode ,
963
+ startingPhpVersion ,
964
+ startingWpVersion
965
+ ) ;
889
966
}
890
967
891
968
// Initial boot
892
- bootPlayground ( currentPhpVersion ) ;
969
+ bootPlayground ( currentPhpVersion , currentWpVersion ) ;
893
970
</ script >
894
971
</ body >
895
972
</ html >
0 commit comments