Skip to content

Commit 4555bc5

Browse files
committed
[feat] Use PHP Mirror to download and install on x64 arch
1 parent 128da80 commit 4555bc5

File tree

6 files changed

+165
-20
lines changed

6 files changed

+165
-20
lines changed

cmd/ch/list.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package ch
2+
3+
import (
4+
"fmt"
5+
"os"
6+
"path/filepath"
7+
8+
"github.com/BrainBuzzer/php-ch/pkg"
9+
"github.com/spf13/cobra"
10+
)
11+
12+
var listCommand = &cobra.Command{
13+
Use: "list",
14+
Short: "List all available PHP versions",
15+
Long: `List all available PHP versions`,
16+
Run: func(cmd *cobra.Command, args []string) {
17+
root := os.Getenv("PHP_HOME")
18+
vs, err := pkg.ListAllVersions()
19+
if err != nil {
20+
fmt.Println("Error while fetching versions: ", err)
21+
}
22+
23+
for _, v := range vs {
24+
installdir := filepath.Join(root, "versions", v.String())
25+
if _, err := os.Stat(installdir); os.IsNotExist(err) {
26+
fmt.Println(v.String())
27+
} else {
28+
fmt.Println(v.String() + "* Installed")
29+
}
30+
}
31+
},
32+
}
33+
34+
func init() {
35+
rootCmd.AddCommand(listCommand)
36+
}

cmd/ch/setup.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ var setupCommand = &cobra.Command{
2626
_, err := exec.Command("php", "-v").Output()
2727
if err != nil {
2828
fmt.Println("No PHP installation found. Installing the latest PHP.")
29-
pkg.ChangeVersion("8.2")
29+
pkg.ChangeVersion("8.2.0")
3030
}
3131

3232
// check if the exec path of php is the same as the PHP_HOME env variable

cmd/ch/version.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package ch
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/spf13/cobra"
7+
)
8+
9+
var versionCommand = &cobra.Command{
10+
Use: "set",
11+
Short: "Set PHP Version",
12+
Aliases: []string{"v"},
13+
Long: `This command checks if there is existing PHP installation for given version, if not, downloads the specified PHP version.`,
14+
Run: func(cmd *cobra.Command, args []string) {
15+
fmt.Println("0.0.3")
16+
},
17+
}
18+
19+
func init() {
20+
rootCmd.AddCommand(versionCommand)
21+
}

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ require (
99
)
1010

1111
require (
12+
github.com/Masterminds/semver/v3 v3.2.0
1213
github.com/inconshreveable/mousetrap v1.1.0 // indirect
1314
github.com/mattn/go-runewidth v0.0.14 // indirect
1415
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g=
2+
github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
13
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
24
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
35
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=

pkg/versions.go

Lines changed: 104 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@ import (
1010
"os"
1111
"os/exec"
1212
"path/filepath"
13+
"sort"
1314
"strings"
1415

16+
"github.com/Masterminds/semver/v3"
1517
"github.com/schollz/progressbar/v3"
1618
)
1719

@@ -20,15 +22,60 @@ var env = Environment{
2022
Symlink: os.Getenv("PHP_SYMLINK"),
2123
}
2224

25+
func ListAllVersions() ([]*semver.Version, error) {
26+
// fetch all versions from https://windows.php.net/downloads/releases/archives/
27+
// print all versions
28+
resp, err := http.Get("https://windows.php.net/downloads/releases/archives/")
29+
if err != nil {
30+
fmt.Println("Error while fetching versions: ", err)
31+
return nil, err
32+
}
33+
defer resp.Body.Close()
34+
35+
body, err := io.ReadAll(resp.Body)
36+
if err != nil {
37+
fmt.Println("Error while fetching versions: ", err)
38+
return nil, err
39+
}
40+
41+
versions := strings.Split(string(body), "php-")
42+
allVersions := make(map[string]bool)
43+
for _, version := range versions {
44+
if strings.Contains(version, "-Win32") && !strings.Contains(version, "pack") {
45+
allVersions[strings.Split(version, "-")[0]] = true
46+
}
47+
}
48+
49+
// convert map[string]bool to []string
50+
var versionsList []string
51+
for version := range allVersions {
52+
versionsList = append(versionsList, version)
53+
}
54+
55+
vs := make([]*semver.Version, len(versionsList))
56+
for i, r := range versionsList {
57+
v, err := semver.NewVersion(r)
58+
if err != nil {
59+
fmt.Println("Error while fetching versions: ", err)
60+
return nil, err
61+
}
62+
63+
vs[i] = v
64+
}
65+
66+
sort.Sort(semver.Collection(vs))
67+
68+
return vs, nil
69+
}
70+
2371
func ChangeVersion(version string) {
2472
// check if there is directory in C:\php\versions\version
2573
// if not, start download
2674
// if yes, run command "cmd /c mklink /D C:\php\current C:\php\versions\version"
2775
installdir := filepath.Join(env.Root, "versions", version)
2876

2977
if _, err := os.Stat(installdir); os.IsNotExist(err) {
30-
fmt.Println("Version", version, "does not exist")
31-
fmt.Println("Downloading " + version + "...")
78+
fmt.Println("Version", version, "does not exist on local machine, checking if version is available on PHP Servers.")
3279
DownloadVersion(version)
3380
} else {
3481
if _, err := os.Stat(env.Symlink); !os.IsNotExist(err) {
@@ -49,24 +96,50 @@ func ChangeVersion(version string) {
4996
}
5097

5198
func DownloadVersion(version string) {
52-
// check if system is 32 or 64 bit
53-
// download the correct version
54-
// extract the zip file
55-
// move all content from where to C:\php\versions\version
56-
// open php.ini from C:\php\versions\version and add the following lines
57-
// extension_dir = "ext"
99+
allVersions, err := ListAllVersions()
100+
if err != nil {
101+
panic(err)
102+
}
103+
104+
isPresent := false
105+
for _, v := range allVersions {
106+
if v.Original() == version {
107+
isPresent = true
108+
break
109+
}
110+
}
111+
112+
if isPresent {
113+
resp, err := http.Get("https://windows.php.net/downloads/releases/archives/")
114+
if err != nil {
115+
fmt.Println("Error while fetching versions: ", err)
116+
}
117+
defer resp.Body.Close()
118+
119+
body, err := io.ReadAll(resp.Body)
120+
if err != nil {
121+
fmt.Println("Error while fetching versions: ", err)
122+
}
123+
124+
versions := strings.Split(string(body), "php-"+version+"-Win32-")
125+
matched := false
126+
for _, v := range versions {
127+
// test regex for php-{version}-Win32-{something}-x64.zip
128+
part := strings.Split(v, ".zip")[0]
129+
if strings.Contains(part, "x64") {
130+
matched = true
131+
fmt.Println("Found x64 version: ", part)
132+
url := "https://windows.php.net/downloads/releases/archives/php-" + version + "-Win32-" + part + ".zip"
133+
fmt.Println("Downloading from: ", url)
134+
downloadAndInstall(url, version)
135+
break
136+
}
137+
}
138+
139+
if !matched {
140+
fmt.Println("Could not find x64 version for PHP " + version)
141+
}
58142

59-
switch version {
60-
case "8.2":
61-
downloadAndInstall("https://windows.php.net/downloads/releases/php-8.2.1-Win32-vs16-x64.zip", version)
62-
case "8.1":
63-
downloadAndInstall("https://windows.php.net/downloads/releases/php-8.1.14-Win32-vs16-x64.zip", version)
64-
case "8.0":
65-
downloadAndInstall("https://windows.php.net/downloads/releases/php-8.0.27-Win32-vs16-x64.zip", version)
66-
case "7.4":
67-
downloadAndInstall("https://windows.php.net/downloads/releases/php-7.4.33-Win32-vc15-x64.zip", version)
68-
default:
69-
fmt.Println("Version", version, "does not exist")
70143
}
71144
}
72145

@@ -141,6 +214,18 @@ func downloadAndInstall(url string, version string) {
141214
// copy php.ini from C:\php\versions\version\php.ini-development to C:\php\versions\version\php.ini
142215
os.Rename(dst+"\\php.ini-development", dst+"\\php.ini")
143216

217+
// edit php.ini and add the following lines
218+
// extension_dir = "ext"
219+
file, err := os.OpenFile(dst+"\\php.ini", os.O_APPEND|os.O_WRONLY, 0644)
220+
if err != nil {
221+
panic(err)
222+
}
223+
defer file.Close()
224+
225+
if _, err = file.WriteString("extension_dir = \"ext\""); err != nil {
226+
panic(err)
227+
}
228+
144229
// change version to the one that was just downloaded
145230
ChangeVersion(version)
146231
}

0 commit comments

Comments
 (0)