1313
1414namespace Ymir \Cli \Command ;
1515
16+ use GuzzleHttp \Client ;
1617use Symfony \Component \Console \Exception \RuntimeException ;
1718use Symfony \Component \Console \Input \InputInterface ;
19+ use Symfony \Component \Filesystem \Filesystem ;
20+ use Symfony \Component \Finder \Finder ;
1821use Symfony \Component \Process \Process ;
22+ use Tightenco \Collect \Support \Arr ;
23+ use Ymir \Cli \ApiClient ;
24+ use Ymir \Cli \CliConfiguration ;
1925use Ymir \Cli \Console \ConsoleOutput ;
26+ use Ymir \Cli \ProjectConfiguration ;
2027
2128class InstallPluginCommand extends AbstractProjectCommand
2229{
@@ -27,6 +34,31 @@ class InstallPluginCommand extends AbstractProjectCommand
2734 */
2835 public const NAME = 'install-plugin ' ;
2936
37+ /**
38+ * The file system.
39+ *
40+ * @var Filesystem
41+ */
42+ private $ filesystem ;
43+
44+ /**
45+ * The project directory where we want to install the plugin.
46+ *
47+ * @var string
48+ */
49+ private $ projectDirectory ;
50+
51+ /**
52+ * Constructor.
53+ */
54+ public function __construct (ApiClient $ apiClient , CliConfiguration $ cliConfiguration , Filesystem $ filesystem , ProjectConfiguration $ projectConfiguration , string $ projectDirectory )
55+ {
56+ parent ::__construct ($ apiClient , $ cliConfiguration , $ projectConfiguration );
57+
58+ $ this ->filesystem = $ filesystem ;
59+ $ this ->projectDirectory = rtrim ($ projectDirectory , '/ ' );
60+ }
61+
3062 /**
3163 * {@inheritdoc}
3264 */
@@ -42,24 +74,76 @@ protected function configure()
4274 */
4375 protected function perform (InputInterface $ input , ConsoleOutput $ output )
4476 {
45- $ command = null ;
46- $ message = 'Installing Ymir plugin ' ;
47- $ projectType = $ this ->projectConfiguration ->getProjectType ();
77+ $ message = 'Installing Ymir plugin ' ;
78+ $ projectType = strtolower ($ this ->projectConfiguration ->getProjectType ());
79+
80+ if (!in_array ($ projectType , ['bedrock ' , 'wordpress ' ])) {
81+ throw new RuntimeException ('Can only install plugin for "bedrock" and "wordpress" projects ' );
82+ }
4883
4984 if ('bedrock ' === $ projectType ) {
50- $ command = ' composer require ymirapp/wordpress-plugin ' ;
51- $ message .= ' using Composer ' ;
85+ $ output -> info ( $ message . ' using Composer ' ) ;
86+ $ this -> installUsingComposer () ;
5287 } elseif ('wordpress ' === $ projectType ) {
53- $ command = ' cp -R /Users/carlalexander/Projects/ymir/wordpress-plugin wp-content/plugins/ymir ' ;
54- $ message .= ' manually ' ;
88+ $ output -> info ( $ message . ' from GitHub ' ) ;
89+ $ this -> installFromGitHub () ;
5590 }
91+ }
5692
57- if (!is_string ($ command )) {
58- throw new RuntimeException ('Unable to install Ymir plugin ' );
93+ /**
94+ * Install the WordPress plugin by downloading it from GitHub.
95+ */
96+ private function installFromGitHub ()
97+ {
98+ $ client = new Client ();
99+ $ response = $ client ->request ('GET ' , 'https://api.github.com/repos/ymirapp/wordpress-plugin/tags ' );
100+
101+ if (200 !== $ response ->getStatusCode ()) {
102+ throw new RuntimeException ('Unable to get the latest WordPress plugin versions from the GitHub API ' );
103+ }
104+
105+ $ latestTag = collect (json_decode ((string ) $ response ->getBody (), true ))->first ();
106+
107+ if (empty ($ latestTag ['zipball_url ' ])) {
108+ throw new RuntimeException ('Unable to parse the WordPress plugin versions from the GitHub API ' );
109+ }
110+
111+ $ downloadedZipFile = tmpfile ();
112+
113+ if (!is_resource ($ downloadedZipFile )) {
114+ throw new RuntimeException ('Unable to open a temporary file ' );
115+ }
116+
117+ fwrite ($ downloadedZipFile , (string ) $ client ->request ('GET ' , $ latestTag ['zipball_url ' ])->getBody ());
118+
119+ $ downloadedZipArchive = new \ZipArchive ();
120+
121+ if (true !== $ downloadedZipArchive ->open (stream_get_meta_data ($ downloadedZipFile )['uri ' ])) {
122+ throw new RuntimeException ('Unable to open the WordPress plugin Zip archive from GitHub ' );
123+ }
124+
125+ $ pluginsDirectory = $ this ->projectDirectory .'/wp-content/plugins ' ;
126+ $ downloadedZipArchive ->extractTo ($ pluginsDirectory );
127+
128+ $ files = Finder::create ()
129+ ->directories ()
130+ ->in ($ pluginsDirectory )
131+ ->path ('/^ymirapp-wordpress-plugin-/ ' )
132+ ->depth ('== 0 ' );
133+
134+ if (1 !== count ($ files )) {
135+ throw new RuntimeException ('Unable to find the extracted WordPress plugin ' );
59136 }
60137
61- $ output ->info ($ message );
62- $ process = Process::fromShellCommandline ($ command );
138+ $ this ->filesystem ->rename ($ pluginsDirectory .'/ ' .Arr::first ($ files )->getFilename (), $ pluginsDirectory .'/ymir-wordpress-plugin ' , true );
139+ }
140+
141+ /**
142+ * Install the WordPress plugin using composer.
143+ */
144+ private function installUsingComposer ()
145+ {
146+ $ process = Process::fromShellCommandline ('composer require ymirapp/wordpress-plugin ' );
63147 $ process ->run ();
64148
65149 if (!$ process ->isSuccessful ()) {
0 commit comments