├── .gitignore
├── stubs
├── res
│ ├── mipmap-hdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ ├── mipmap-mdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ ├── mipmap-xhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ ├── mipmap-xxxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ ├── mipmap-anydpi-v26
│ │ ├── ic_launcher.xml
│ │ └── ic_launcher_round.xml
│ ├── values
│ │ └── colors.xml
│ ├── values-night
│ │ └── themes.xml
│ ├── drawable-v24
│ │ └── ic_launcher_foreground.xml
│ └── drawable
│ │ └── ic_launcher_background.xml
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── .gitignore
├── gradlew.bat
└── gradlew
├── tasks
├── stub.php
└── generate_phar.php
├── composer.json
├── index.php
├── LICENSE.md
├── src
├── HelpersTrait.php
├── ChangableTrait.php
└── GenerateCommand.php
├── README.md
└── composer.lock
/.gitignore:
--------------------------------------------------------------------------------
1 | /vendor
2 | /tasks
3 | *.phar
4 |
--------------------------------------------------------------------------------
/stubs/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnandPilania/php-android-cli/HEAD/stubs/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/stubs/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnandPilania/php-android-cli/HEAD/stubs/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/stubs/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnandPilania/php-android-cli/HEAD/stubs/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/stubs/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnandPilania/php-android-cli/HEAD/stubs/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/stubs/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnandPilania/php-android-cli/HEAD/stubs/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/stubs/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnandPilania/php-android-cli/HEAD/stubs/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/tasks/stub.php:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env php
2 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/stubs/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/index.php:
--------------------------------------------------------------------------------
1 | add(new \KSPEdu\PHPAndroidCli\GenerateCommand());
12 | $app->run();
13 |
--------------------------------------------------------------------------------
/stubs/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FFBB86FC
4 | #FF6200EE
5 | #FF3700B3
6 | #FF03DAC5
7 | #FF018786
8 | #FF000000
9 | #FFFFFFFF
10 |
--------------------------------------------------------------------------------
/stubs/res/values-night/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
16 |
--------------------------------------------------------------------------------
/tasks/generate_phar.php:
--------------------------------------------------------------------------------
1 | hasChildren() && !in_array($file->getFilename(), $exclude)) {
20 | return true;
21 | }
22 | return $file->isFile() && !in_array($file->getFilename(), $exclude);
23 | };
24 |
25 | $innerIterator = new RecursiveDirectoryIterator(BASEDIR, RecursiveDirectoryIterator::SKIP_DOTS);
26 |
27 | $iterator = new RecursiveIteratorIterator(new RecursiveCallbackFilterIterator($innerIterator, $filter));
28 |
29 | $phar = new \Phar('phpandroid.phar', 0, 'phpandroid.phar');
30 | $phar->setSignatureAlgorithm(\Phar::SHA1);
31 | $phar->startBuffering();
32 | $phar->buildFromIterator($iterator, BASEDIR);
33 | $phar->setStub(file_get_contents(BUILDDIR . '/stub.php'));
34 | $phar->stopBuffering();
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Anand Pilania
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/stubs/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
9 |
10 |
16 |
19 |
22 |
23 |
24 |
25 |
31 |
--------------------------------------------------------------------------------
/stubs/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/src/HelpersTrait.php:
--------------------------------------------------------------------------------
1 | deleteExisting($target . GenerateCommand::DS . $obj);
15 | } else {
16 | unlink($target . GenerateCommand::DS . $obj);
17 | }
18 | }
19 | }
20 | rmdir($target);
21 | }
22 | }
23 | protected function copyr($src, $dest)
24 | {
25 | if (is_link($src)) {
26 | return symlink(readlink($src), $dest);
27 | }
28 |
29 | if (is_file($src)) {
30 | return copy($src, $dest);
31 | }
32 |
33 | $this->_mkdir($dest);
34 |
35 | $dir = dir($src);
36 | while (false !== $entry = $dir->read()) {
37 | if ($entry == '.' || $entry == '..') {
38 | continue;
39 | }
40 |
41 | $this->copyr($src . GenerateCommand::DS . $entry, $dest . GenerateCommand::DS . $entry);
42 | }
43 |
44 | $dir->close();
45 | return true;
46 | }
47 | protected function str_contains($haystack, $needles)
48 | {
49 | foreach ((array) $needles as $needle) {
50 | if ($needle != '' && mb_strpos($haystack, $needle) !== false) {
51 | return true;
52 | }
53 | }
54 | return false;
55 | }
56 | protected function _mkdir($dest)
57 | {
58 | if (!file_exists($dest) || !is_dir($dest)) {
59 | //$this->_print_info("$dest\n");
60 | mkdir($dest);
61 | }
62 | }
63 |
64 | protected function _print_info($message)
65 | {
66 | $this->output->writeln('' . $message . '');
67 | }
68 |
69 | protected function isKotlin()
70 | {
71 | return strtoupper($this->getInputOption('type')) === 'KOTLIN';
72 | }
73 |
74 | protected function isLegacy()
75 | {
76 | return $this->getInputOption('legacy');
77 | }
78 |
79 | protected function getInputOption($option)
80 | {
81 | return $this->input->getOption($option);
82 | }
83 |
84 | protected function nameForAsset($moduleName)
85 | {
86 | return ucfirst(strtolower($moduleName) === 'app' ? $this->projectName : $moduleName);
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # PHP Android CLI
2 |
3 | [](https://hits.seeyoufarm.com)
4 |
5 | PHP Android CLI create/generate Scaffold Android-Studio Gradle project with:
6 |
7 | - `Java` or `Kotlin` language,
8 | - `legacy` or standard package
9 | - Modules (application/library)
10 | - Variants with Dimensions
11 | - Scaffold project & application/library level `build.gradle` with package name & `dimensions` & `variants`
12 | - Manage `settings.gradle`
13 | - Generate `manifest` file & `res` with default `icon`, `color`, `style` & `values`
14 | - ...
15 |
16 | # New Features!
17 |
18 | - Language select `java` or `kotlin`
19 | - Version `legacy` or standard
20 |
21 | # Removed!
22 |
23 | - `androidX` selection,
24 | - `jetifier` selection,
25 |
26 | You can also:
27 |
28 | - set `targetSdk`
29 | - set `buildToolsVersion`
30 | - set `minSdk` & `maxSdk`
31 | - `JAVA` or `KOTLIN`
32 | - `legacy`
33 |
34 | ### Tech
35 |
36 | PHP Android CLI uses:
37 |
38 | - [Symfony Console](https://symfony.com/console) - ...
39 |
40 | And of course `PHP Android CLI` itself is open source with a [public repository](https://github.com/AnandPilania/php-android-cli) on GitHub.
41 |
42 | ### Installation
43 |
44 | PHP Android CLI requires [PHP](https://php.net/) v5+ to run.
45 |
46 | Just download the [`phpandroid`](https://github.com/AnandPilania/php-android-cli/releases/latest) and start scaffolding.
47 |
48 | ```sh
49 | $ phpandroid create [OPTIONS]
50 | ```
51 |
52 | ## USAGE
53 |
54 | ### Basic use
55 |
56 | Create `HelloWorld` project with `com.example.helloworld` package name:
57 |
58 | ```sh
59 | phpandroid create HelloWorld com.example.helloworld
60 | ```
61 |
62 | ### Create `Modules` along with `App`
63 |
64 | Create `HelloWorld` project with `sdk` library & `admin` application
65 |
66 | ```sh
67 | phpandroid create HelloWorld com.example.helloworld --modules=sdk:library,admin
68 | ```
69 |
70 | ### Create `productVariants`: `free` & `paid` variant
71 |
72 | ```sh
73 | phpandroid create HelloWorld com.example.helloworld --variants=free:type,paid:type
74 | ```
75 |
76 | here `type` is the `dimension`
77 |
78 | ## Options
79 |
80 | ### Default
81 |
82 | PHP Android CLI is currently using default values for latest Android. These are:
83 |
84 | | OPTIONS | Usage | DEFAULT |
85 | | -------------------- | ----------------------- | -------- |
86 | | `--type`/`-t` | set `type` | `kotlin` |
87 | | `--legacy`/`-l` | set `legacy` | `false` |
88 | | `--compileSdk`/`-cs` | set `targetSdk` | 31 |
89 | | `--buildTools`/`-bt` | set `buildToolsVersion` | 31.0.0 |
90 | | `--minSdk`/`-ms` | set `minSdk` | 21 |
91 | | `--targetSdk`/`-ts` | set `maxSdk` | 31 |
92 |
93 | Use `--force` to re-write existing project.
94 |
95 | ### Todos
96 |
97 | - Create/Scaffold `activity`
98 | - Create/Scaffold `variants` source
99 | - ...
100 |
101 | ## License
102 |
103 | MIT
104 |
105 | **Free Software, Hell Yeah!**
106 |
--------------------------------------------------------------------------------
/stubs/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
10 |
12 |
14 |
16 |
18 |
20 |
22 |
24 |
26 |
28 |
30 |
32 |
34 |
36 |
38 |
40 |
42 |
44 |
46 |
48 |
50 |
52 |
54 |
56 |
58 |
60 |
62 |
64 |
66 |
68 |
70 |
72 |
74 |
75 |
--------------------------------------------------------------------------------
/stubs/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/src/ChangableTrait.php:
--------------------------------------------------------------------------------
1 | getInputOption('compileSdk') . '
51 | buildToolsVersion "' . $this->getInputOption('buildTools') . '"
52 |
53 | defaultConfig {
54 | applicationId "' . $this->pkgName . '"
55 | minSdkVersion ' . $this->getInputOption('minSdk') . '
56 | targetSdkVersion ' . $this->getInputOption('targetSdk') . '
57 | versionCode 1
58 | versionName "1.0"
59 |
60 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
61 | }
62 |
63 | buildTypes {
64 | release {
65 | minifyEnabled false
66 | proguardFiles getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro"
67 | }
68 | }
69 | compileOptions {
70 | sourceCompatibility JavaVersion.VERSION_1_8
71 | targetCompatibility JavaVersion.VERSION_1_8
72 | }
73 | ' . ($isKotlin ? 'kotlinOptions {
74 | jvmTarget = "1.8"
75 | }' : '') . '
76 | }
77 |
78 | dependencies {
79 |
80 | ' . ($isKotlin ? 'implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"' : '') . '
81 | implementation "com.android.support:appcompat-v7:28.0.0"
82 | testImplementation "junit:junit:4.+"
83 | androidTestImplementation "com.android.support.test:runner:1.0.2"
84 | androidTestImplementation "com.android.support.test.espresso:espresso-core:3.0.2"
85 | }
86 | ';
87 | }
88 |
89 | protected function gradleProperties($isKotlin)
90 | {
91 | return "
92 | # Project-wide Gradle settings.
93 | # IDE (e.g. Android Studio) users:
94 | # Gradle settings configured through the IDE *will override*
95 | # any settings specified in this file.
96 | # For more details on how to configure your build environment visit
97 | # http://www.gradle.org/docs/current/userguide/build_environment.html
98 | # Specifies the JVM arguments used for the daemon process.
99 | # The setting is particularly useful for tweaking memory settings.
100 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
101 | # When configured, Gradle will run in incubating parallel mode.
102 | # This option should only be used with decoupled projects. More details, visit
103 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
104 | # org.gradle.parallel=true
105 | # Kotlin code style for this project: \"official\" or \"obsolete\":
106 | " . ($isKotlin ? "kotlin.code.style=official" : '') . "
107 | ";
108 | }
109 |
110 | protected function manifestApplicationFile($moduleName)
111 | {
112 | return '
113 |
114 |
116 |
117 |
124 |
125 |
126 | ';
127 | }
128 |
129 | // TODO:
130 | protected function manifestModuleFile($moduleName, $moduleType)
131 | {
132 | return '
133 |
135 |
136 | ' . ($moduleType === 'library' ? '' : '
143 | ') . '
144 |
145 | ';
146 | }
147 |
148 | protected function proguardFile()
149 | {
150 | return <<
179 | ' . ('app' === $moduleName ? $this->projectName : $moduleName) . '
180 |
181 | ';
182 | }
183 |
184 | protected function themesFile($moduleName, $isDark = false)
185 | {
186 | return '
187 |
188 |
189 |
202 |
203 | ';
204 | }
205 | }
206 |
--------------------------------------------------------------------------------
/src/GenerateCommand.php:
--------------------------------------------------------------------------------
1 | setName('create')
24 | ->setDescription('Create android studio gradle project skeleton')
25 | ->addArgument('project', InputArgument::REQUIRED, 'Provide the project name')
26 | ->addArgument('pkg', InputArgument::REQUIRED, 'Provide the pkg name')
27 | ->addOption('targetSdk', 'ts', InputOption::VALUE_OPTIONAL, 'Pass the targetSdk.', 31)
28 | ->addOption('minSdk', 'ms', InputOption::VALUE_OPTIONAL, 'Pass the minSdk.', 21)
29 | ->addOption('compileSdk', 'cs', InputOption::VALUE_OPTIONAL, 'Pass the compileSdk.', 31)
30 | ->addOption('buildTools', 'bt', InputOption::VALUE_OPTIONAL, 'Pass the buildVersion.', '31.0.0')
31 | ->addOption('type', 't', InputOption::VALUE_OPTIONAL, 'JAVA or KOTLIN', 'kotlin')
32 | ->addOption('legacy', 'l', InputOption::VALUE_OPTIONAL, 'Using Legacy deps?', false)
33 | ->addOption('modules', 'm', InputOption::VALUE_OPTIONAL, 'Comma-seperated modules [with semi-colon seperated type] (backend:library,client)')
34 | ->addOption('flavors', 'f', InputOption::VALUE_OPTIONAL, 'Comma-seperated flavors followed by dimension with semi-colon (free:type,paid:type,php:backend,firebase:backend)')
35 | ->addOption('force', null)
36 | ->setHelp(
37 | <<%command.name% command helps you generates new Android-Studio Gradle Project.
39 |
40 | By default, the command interacts with the developer to tweak the generation.
41 | Any passed option will be used as a default value for the interaction
42 | (project & pkg is the only two needed if you follow the conventions):
43 |
44 | php %command.full_name% HelloWorld com.example.helloworld
45 |
46 | If you want to disable any user interaction, use --no-interaction
47 | EOT
48 | );
49 | }
50 |
51 | protected function execute(InputInterface $input, OutputInterface $output)
52 | {
53 | $this->input = $input;
54 | $this->output = $output;
55 |
56 | $this->projectName = $input->getArgument('project');
57 | $this->pkgName = $input->getArgument('pkg');
58 |
59 | $this->generateOptions();
60 | $this->createProject();
61 |
62 | return 0;
63 | }
64 |
65 | private function createProject()
66 | {
67 | if (is_dir($this->projectName)) {
68 | if (!$this->input->getOption('force')) {
69 | $this->output->writeln('Project ' . $this->projectName . ' is already exists!>');
70 | $this->output->writeln('Use: --force/-ff for forcefully delete an existing project!');
71 | exit();
72 | } else {
73 | $this->deleteExisting($this->projectName);
74 | }
75 | }
76 |
77 | $this->_mkdir($this->projectName);
78 | $this->copyr($this->stubsPath . 'gradle', $this->projectName . self::DS . 'gradle');
79 | copy($this->stubsPath . 'gradlew', $this->projectName . self::DS . 'gradlew');
80 | copy($this->stubsPath . 'gradlew.bat', $this->projectName . self::DS . 'gradlew.bat');
81 | copy($this->stubsPath . '.gitignore', $this->projectName . self::DS . '.gitignore');
82 | $this->_mkdir($this->projectName . self::DS . 'build');
83 |
84 | file_put_contents($this->projectName . self::DS . 'build.gradle', $this->projectBuildGradle($this->isKotlin()), 0);
85 | file_put_contents($this->projectName . self::DS . 'gradle.properties', $this->gradleProperties($this->isKotlin()), 0);
86 |
87 | $settingsContent = "include ";
88 |
89 | foreach ($this->modules as $key => $module) {
90 | $exModule = explode(':', $module);
91 | if ($exModule > 0) {
92 | $moduleName = $exModule[0];
93 | $moduleType = isset($exModule[1]) ? $exModule[1] : 'application';
94 | }
95 |
96 | $this->_mkdir($this->projectName . self::DS . $moduleName);
97 |
98 | file_put_contents($this->projectName . self::DS . $moduleName . self::DS . '.gitignore', "/build\n\n", 0);
99 |
100 | $fdCount = 0;
101 | $flavorContent = '';
102 | $dimensionContent = '';
103 | if ($count = count($this->flavors)) {
104 | $flavorContent = "productFlavors {\n\t\t";
105 | $dimensionContent = 'flavorDimensions ';
106 | foreach ($this->flavors as $flavor => $dimension) {
107 | $dimenPushed = $this->str_contains($dimensionContent, "'$dimension'");
108 | if (!$dimenPushed) {
109 | $dimensionContent .= "'$dimension'";
110 | }
111 | $flavorContent .= $flavor . " {\n\t\t\tdimension '$dimension'\n\t\t}";
112 |
113 | if ($fdCount < ($count - 1)) {
114 | $fdCount = $fdCount + 1;
115 | if (!$dimenPushed) {
116 | $dimensionContent .= ", ";
117 | }
118 | $flavorContent .= "\n\t\t";
119 | }
120 | }
121 | $flavorContent .= "\n\t}\n";
122 | }
123 | $fdContent = $dimensionContent . "\n\t" . $flavorContent;
124 |
125 | file_put_contents(
126 | $this->projectName . self::DS . $moduleName . self::DS . 'build.gradle',
127 | $this->appBuildGradle($this->isKotlin()),
128 | 0
129 | );
130 | file_put_contents($this->projectName . self::DS . $moduleName . self::DS . 'proguard-rules.pro', $this->proguardFile(), 0);
131 |
132 | $this->_mkdir($this->projectName . self::DS . $moduleName . self::DS . 'src');
133 | $this->_mkdir($this->projectName . self::DS . $moduleName . self::DS . 'build');
134 | $this->_mkdir($this->projectName . self::DS . $moduleName . self::DS . 'libs');
135 |
136 | $this->_mkdir($this->projectName . self::DS . $moduleName . self::DS . 'src/androidTest');
137 | $this->_mkdir($this->projectName . self::DS . $moduleName . self::DS . 'src/test');
138 | $this->_mkdir($this->projectName . self::DS . $moduleName . self::DS . 'src/main');
139 |
140 | file_put_contents(
141 | $this->projectName . self::DS . $moduleName . self::DS . 'src/main/AndroidManifest.xml',
142 | $moduleType === 'application' ? $this->manifestApplicationFile($this->nameForAsset($moduleName)) : $this->manifestModuleFile($moduleName, $moduleType),
143 | 0
144 | );
145 |
146 | $this->_mkdir($this->projectName . self::DS . $moduleName . self::DS . 'src/main/java');
147 | $exPkg = explode('.', $this->pkgName);
148 | $_dir = $this->projectName . self::DS . $moduleName . self::DS . 'src/main/java';
149 | $_newDir = '';
150 | foreach ($exPkg as $key => $pkgDir) {
151 | $_newDir .= self::DS . $pkgDir;
152 | $this->_mkdir($_dir . $_newDir);
153 | if ($key === (count($exPkg) - 1) && $moduleName !== 'app') {
154 | $this->_mkdir($_dir . $_newDir . self::DS . $moduleName);
155 | }
156 | }
157 |
158 | if ($moduleType === 'library') {
159 | $this->_mkdir($this->projectName . self::DS . $moduleName . self::DS . 'src' . self::DS . 'main' . self::DS . 'res');
160 | $this->_mkdir($this->projectName . self::DS . $moduleName . self::DS . 'src' . self::DS . 'main' . self::DS . 'res' . self::DS . 'drawable');
161 | $this->_mkdir($this->projectName . self::DS . $moduleName . self::DS . 'src' . self::DS . 'main' . self::DS . 'res' . self::DS . 'values');
162 | } else {
163 | $this->copyr($this->stubsPath . 'res', $this->projectName . self::DS . $moduleName . self::DS . 'src' . self::DS . 'main' . self::DS . 'res');
164 | }
165 | file_put_contents($this->projectName . self::DS . $moduleName . self::DS . 'src/main/res/values/strings.xml', $this->stringsFile($this->nameForAsset($moduleName)), 0);
166 | file_put_contents($this->projectName . self::DS . $moduleName . self::DS . 'src/main/res/values/themes.xml', $this->themesFile($this->nameForAsset($moduleName)), 0);
167 | file_put_contents($this->projectName . self::DS . $moduleName . self::DS . 'src/main/res/values-night/themes.xml', $this->themesFile($this->nameForAsset($moduleName), true), 0);
168 |
169 | $settingsContent .= "':" . $moduleName . "'";
170 |
171 | if ($key < (count($this->modules) - 1)) {
172 | $settingsContent .= ",";
173 | }
174 | }
175 | file_put_contents($this->projectName . self::DS . 'settings.gradle', $settingsContent . "\n", 0);
176 | // file_put_contents($this->projectName . DIRECTORY_SEPARATOR . 'local.properties', "ndk.dir=E\:\\SDK\\ndk-bundle\nsdk.dir=E\:\\SDK\n", 0);
177 |
178 | $this->output->writeln('' . $this->projectName . ' created successfully!');
179 | }
180 |
181 | private function generateOptions()
182 | {
183 | $this->generateFlavors($this->input->getOption('flavors'));
184 | $this->generateModules($this->input->getOption('modules'));
185 | }
186 |
187 | private function generateFlavors($flavors = null)
188 | {
189 | if ($flavors) {
190 | $flavors = explode(',', $flavors);
191 | if (is_array($flavors) && count($flavors)) {
192 | foreach ($flavors as $flavor) {
193 | $exFlavor = explode(':', $flavor);
194 | if (!isset($exFlavor[1])) {
195 | $this->output->writeln('Flavors must-be followed by specific dimension>');
196 | exit();
197 | }
198 |
199 | $this->flavors[$exFlavor[0]] = $exFlavor[1];
200 | }
201 | }
202 | }
203 | }
204 | private function generateModules($modules = null)
205 | {
206 | if ($modules) {
207 | $modules = explode(',', $modules);
208 | if (is_array($modules) && count($modules)) {
209 | $_mergedModules = array_merge($this->modules, $modules);
210 | $this->modules = $_mergedModules;
211 | }
212 | }
213 | }
214 | }
215 |
--------------------------------------------------------------------------------
/composer.lock:
--------------------------------------------------------------------------------
1 | {
2 | "_readme": [
3 | "This file locks the dependencies of your project to a known state",
4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
5 | "This file is @generated automatically"
6 | ],
7 | "content-hash": "ccda0f1fbd5b4f64d57743fa6288ecac",
8 | "packages": [
9 | {
10 | "name": "psr/container",
11 | "version": "1.1.1",
12 | "source": {
13 | "type": "git",
14 | "url": "https://github.com/php-fig/container.git",
15 | "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf"
16 | },
17 | "dist": {
18 | "type": "zip",
19 | "url": "https://api.github.com/repos/php-fig/container/zipball/8622567409010282b7aeebe4bb841fe98b58dcaf",
20 | "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf",
21 | "shasum": ""
22 | },
23 | "require": {
24 | "php": ">=7.2.0"
25 | },
26 | "type": "library",
27 | "autoload": {
28 | "psr-4": {
29 | "Psr\\Container\\": "src/"
30 | }
31 | },
32 | "notification-url": "https://packagist.org/downloads/",
33 | "license": [
34 | "MIT"
35 | ],
36 | "authors": [
37 | {
38 | "name": "PHP-FIG",
39 | "homepage": "https://www.php-fig.org/"
40 | }
41 | ],
42 | "description": "Common Container Interface (PHP FIG PSR-11)",
43 | "homepage": "https://github.com/php-fig/container",
44 | "keywords": [
45 | "PSR-11",
46 | "container",
47 | "container-interface",
48 | "container-interop",
49 | "psr"
50 | ],
51 | "support": {
52 | "issues": "https://github.com/php-fig/container/issues",
53 | "source": "https://github.com/php-fig/container/tree/1.1.1"
54 | },
55 | "time": "2021-03-05T17:36:06+00:00"
56 | },
57 | {
58 | "name": "symfony/console",
59 | "version": "v5.3.7",
60 | "source": {
61 | "type": "git",
62 | "url": "https://github.com/symfony/console.git",
63 | "reference": "8b1008344647462ae6ec57559da166c2bfa5e16a"
64 | },
65 | "dist": {
66 | "type": "zip",
67 | "url": "https://api.github.com/repos/symfony/console/zipball/8b1008344647462ae6ec57559da166c2bfa5e16a",
68 | "reference": "8b1008344647462ae6ec57559da166c2bfa5e16a",
69 | "shasum": ""
70 | },
71 | "require": {
72 | "php": ">=7.2.5",
73 | "symfony/deprecation-contracts": "^2.1",
74 | "symfony/polyfill-mbstring": "~1.0",
75 | "symfony/polyfill-php73": "^1.8",
76 | "symfony/polyfill-php80": "^1.16",
77 | "symfony/service-contracts": "^1.1|^2",
78 | "symfony/string": "^5.1"
79 | },
80 | "conflict": {
81 | "psr/log": ">=3",
82 | "symfony/dependency-injection": "<4.4",
83 | "symfony/dotenv": "<5.1",
84 | "symfony/event-dispatcher": "<4.4",
85 | "symfony/lock": "<4.4",
86 | "symfony/process": "<4.4"
87 | },
88 | "provide": {
89 | "psr/log-implementation": "1.0|2.0"
90 | },
91 | "require-dev": {
92 | "psr/log": "^1|^2",
93 | "symfony/config": "^4.4|^5.0",
94 | "symfony/dependency-injection": "^4.4|^5.0",
95 | "symfony/event-dispatcher": "^4.4|^5.0",
96 | "symfony/lock": "^4.4|^5.0",
97 | "symfony/process": "^4.4|^5.0",
98 | "symfony/var-dumper": "^4.4|^5.0"
99 | },
100 | "suggest": {
101 | "psr/log": "For using the console logger",
102 | "symfony/event-dispatcher": "",
103 | "symfony/lock": "",
104 | "symfony/process": ""
105 | },
106 | "type": "library",
107 | "autoload": {
108 | "psr-4": {
109 | "Symfony\\Component\\Console\\": ""
110 | },
111 | "exclude-from-classmap": [
112 | "/Tests/"
113 | ]
114 | },
115 | "notification-url": "https://packagist.org/downloads/",
116 | "license": [
117 | "MIT"
118 | ],
119 | "authors": [
120 | {
121 | "name": "Fabien Potencier",
122 | "email": "fabien@symfony.com"
123 | },
124 | {
125 | "name": "Symfony Community",
126 | "homepage": "https://symfony.com/contributors"
127 | }
128 | ],
129 | "description": "Eases the creation of beautiful and testable command line interfaces",
130 | "homepage": "https://symfony.com",
131 | "keywords": [
132 | "cli",
133 | "command line",
134 | "console",
135 | "terminal"
136 | ],
137 | "support": {
138 | "source": "https://github.com/symfony/console/tree/v5.3.7"
139 | },
140 | "funding": [
141 | {
142 | "url": "https://symfony.com/sponsor",
143 | "type": "custom"
144 | },
145 | {
146 | "url": "https://github.com/fabpot",
147 | "type": "github"
148 | },
149 | {
150 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
151 | "type": "tidelift"
152 | }
153 | ],
154 | "time": "2021-08-25T20:02:16+00:00"
155 | },
156 | {
157 | "name": "symfony/deprecation-contracts",
158 | "version": "v2.4.0",
159 | "source": {
160 | "type": "git",
161 | "url": "https://github.com/symfony/deprecation-contracts.git",
162 | "reference": "5f38c8804a9e97d23e0c8d63341088cd8a22d627"
163 | },
164 | "dist": {
165 | "type": "zip",
166 | "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/5f38c8804a9e97d23e0c8d63341088cd8a22d627",
167 | "reference": "5f38c8804a9e97d23e0c8d63341088cd8a22d627",
168 | "shasum": ""
169 | },
170 | "require": {
171 | "php": ">=7.1"
172 | },
173 | "type": "library",
174 | "extra": {
175 | "branch-alias": {
176 | "dev-main": "2.4-dev"
177 | },
178 | "thanks": {
179 | "name": "symfony/contracts",
180 | "url": "https://github.com/symfony/contracts"
181 | }
182 | },
183 | "autoload": {
184 | "files": [
185 | "function.php"
186 | ]
187 | },
188 | "notification-url": "https://packagist.org/downloads/",
189 | "license": [
190 | "MIT"
191 | ],
192 | "authors": [
193 | {
194 | "name": "Nicolas Grekas",
195 | "email": "p@tchwork.com"
196 | },
197 | {
198 | "name": "Symfony Community",
199 | "homepage": "https://symfony.com/contributors"
200 | }
201 | ],
202 | "description": "A generic function and convention to trigger deprecation notices",
203 | "homepage": "https://symfony.com",
204 | "support": {
205 | "source": "https://github.com/symfony/deprecation-contracts/tree/v2.4.0"
206 | },
207 | "funding": [
208 | {
209 | "url": "https://symfony.com/sponsor",
210 | "type": "custom"
211 | },
212 | {
213 | "url": "https://github.com/fabpot",
214 | "type": "github"
215 | },
216 | {
217 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
218 | "type": "tidelift"
219 | }
220 | ],
221 | "time": "2021-03-23T23:28:01+00:00"
222 | },
223 | {
224 | "name": "symfony/polyfill-ctype",
225 | "version": "v1.23.0",
226 | "source": {
227 | "type": "git",
228 | "url": "https://github.com/symfony/polyfill-ctype.git",
229 | "reference": "46cd95797e9df938fdd2b03693b5fca5e64b01ce"
230 | },
231 | "dist": {
232 | "type": "zip",
233 | "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/46cd95797e9df938fdd2b03693b5fca5e64b01ce",
234 | "reference": "46cd95797e9df938fdd2b03693b5fca5e64b01ce",
235 | "shasum": ""
236 | },
237 | "require": {
238 | "php": ">=7.1"
239 | },
240 | "suggest": {
241 | "ext-ctype": "For best performance"
242 | },
243 | "type": "library",
244 | "extra": {
245 | "branch-alias": {
246 | "dev-main": "1.23-dev"
247 | },
248 | "thanks": {
249 | "name": "symfony/polyfill",
250 | "url": "https://github.com/symfony/polyfill"
251 | }
252 | },
253 | "autoload": {
254 | "psr-4": {
255 | "Symfony\\Polyfill\\Ctype\\": ""
256 | },
257 | "files": [
258 | "bootstrap.php"
259 | ]
260 | },
261 | "notification-url": "https://packagist.org/downloads/",
262 | "license": [
263 | "MIT"
264 | ],
265 | "authors": [
266 | {
267 | "name": "Gert de Pagter",
268 | "email": "BackEndTea@gmail.com"
269 | },
270 | {
271 | "name": "Symfony Community",
272 | "homepage": "https://symfony.com/contributors"
273 | }
274 | ],
275 | "description": "Symfony polyfill for ctype functions",
276 | "homepage": "https://symfony.com",
277 | "keywords": [
278 | "compatibility",
279 | "ctype",
280 | "polyfill",
281 | "portable"
282 | ],
283 | "support": {
284 | "source": "https://github.com/symfony/polyfill-ctype/tree/v1.23.0"
285 | },
286 | "funding": [
287 | {
288 | "url": "https://symfony.com/sponsor",
289 | "type": "custom"
290 | },
291 | {
292 | "url": "https://github.com/fabpot",
293 | "type": "github"
294 | },
295 | {
296 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
297 | "type": "tidelift"
298 | }
299 | ],
300 | "time": "2021-02-19T12:13:01+00:00"
301 | },
302 | {
303 | "name": "symfony/polyfill-intl-grapheme",
304 | "version": "v1.23.1",
305 | "source": {
306 | "type": "git",
307 | "url": "https://github.com/symfony/polyfill-intl-grapheme.git",
308 | "reference": "16880ba9c5ebe3642d1995ab866db29270b36535"
309 | },
310 | "dist": {
311 | "type": "zip",
312 | "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/16880ba9c5ebe3642d1995ab866db29270b36535",
313 | "reference": "16880ba9c5ebe3642d1995ab866db29270b36535",
314 | "shasum": ""
315 | },
316 | "require": {
317 | "php": ">=7.1"
318 | },
319 | "suggest": {
320 | "ext-intl": "For best performance"
321 | },
322 | "type": "library",
323 | "extra": {
324 | "branch-alias": {
325 | "dev-main": "1.23-dev"
326 | },
327 | "thanks": {
328 | "name": "symfony/polyfill",
329 | "url": "https://github.com/symfony/polyfill"
330 | }
331 | },
332 | "autoload": {
333 | "psr-4": {
334 | "Symfony\\Polyfill\\Intl\\Grapheme\\": ""
335 | },
336 | "files": [
337 | "bootstrap.php"
338 | ]
339 | },
340 | "notification-url": "https://packagist.org/downloads/",
341 | "license": [
342 | "MIT"
343 | ],
344 | "authors": [
345 | {
346 | "name": "Nicolas Grekas",
347 | "email": "p@tchwork.com"
348 | },
349 | {
350 | "name": "Symfony Community",
351 | "homepage": "https://symfony.com/contributors"
352 | }
353 | ],
354 | "description": "Symfony polyfill for intl's grapheme_* functions",
355 | "homepage": "https://symfony.com",
356 | "keywords": [
357 | "compatibility",
358 | "grapheme",
359 | "intl",
360 | "polyfill",
361 | "portable",
362 | "shim"
363 | ],
364 | "support": {
365 | "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.23.1"
366 | },
367 | "funding": [
368 | {
369 | "url": "https://symfony.com/sponsor",
370 | "type": "custom"
371 | },
372 | {
373 | "url": "https://github.com/fabpot",
374 | "type": "github"
375 | },
376 | {
377 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
378 | "type": "tidelift"
379 | }
380 | ],
381 | "time": "2021-05-27T12:26:48+00:00"
382 | },
383 | {
384 | "name": "symfony/polyfill-intl-normalizer",
385 | "version": "v1.23.0",
386 | "source": {
387 | "type": "git",
388 | "url": "https://github.com/symfony/polyfill-intl-normalizer.git",
389 | "reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8"
390 | },
391 | "dist": {
392 | "type": "zip",
393 | "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8590a5f561694770bdcd3f9b5c69dde6945028e8",
394 | "reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8",
395 | "shasum": ""
396 | },
397 | "require": {
398 | "php": ">=7.1"
399 | },
400 | "suggest": {
401 | "ext-intl": "For best performance"
402 | },
403 | "type": "library",
404 | "extra": {
405 | "branch-alias": {
406 | "dev-main": "1.23-dev"
407 | },
408 | "thanks": {
409 | "name": "symfony/polyfill",
410 | "url": "https://github.com/symfony/polyfill"
411 | }
412 | },
413 | "autoload": {
414 | "psr-4": {
415 | "Symfony\\Polyfill\\Intl\\Normalizer\\": ""
416 | },
417 | "files": [
418 | "bootstrap.php"
419 | ],
420 | "classmap": [
421 | "Resources/stubs"
422 | ]
423 | },
424 | "notification-url": "https://packagist.org/downloads/",
425 | "license": [
426 | "MIT"
427 | ],
428 | "authors": [
429 | {
430 | "name": "Nicolas Grekas",
431 | "email": "p@tchwork.com"
432 | },
433 | {
434 | "name": "Symfony Community",
435 | "homepage": "https://symfony.com/contributors"
436 | }
437 | ],
438 | "description": "Symfony polyfill for intl's Normalizer class and related functions",
439 | "homepage": "https://symfony.com",
440 | "keywords": [
441 | "compatibility",
442 | "intl",
443 | "normalizer",
444 | "polyfill",
445 | "portable",
446 | "shim"
447 | ],
448 | "support": {
449 | "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.23.0"
450 | },
451 | "funding": [
452 | {
453 | "url": "https://symfony.com/sponsor",
454 | "type": "custom"
455 | },
456 | {
457 | "url": "https://github.com/fabpot",
458 | "type": "github"
459 | },
460 | {
461 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
462 | "type": "tidelift"
463 | }
464 | ],
465 | "time": "2021-02-19T12:13:01+00:00"
466 | },
467 | {
468 | "name": "symfony/polyfill-mbstring",
469 | "version": "v1.23.1",
470 | "source": {
471 | "type": "git",
472 | "url": "https://github.com/symfony/polyfill-mbstring.git",
473 | "reference": "9174a3d80210dca8daa7f31fec659150bbeabfc6"
474 | },
475 | "dist": {
476 | "type": "zip",
477 | "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9174a3d80210dca8daa7f31fec659150bbeabfc6",
478 | "reference": "9174a3d80210dca8daa7f31fec659150bbeabfc6",
479 | "shasum": ""
480 | },
481 | "require": {
482 | "php": ">=7.1"
483 | },
484 | "suggest": {
485 | "ext-mbstring": "For best performance"
486 | },
487 | "type": "library",
488 | "extra": {
489 | "branch-alias": {
490 | "dev-main": "1.23-dev"
491 | },
492 | "thanks": {
493 | "name": "symfony/polyfill",
494 | "url": "https://github.com/symfony/polyfill"
495 | }
496 | },
497 | "autoload": {
498 | "psr-4": {
499 | "Symfony\\Polyfill\\Mbstring\\": ""
500 | },
501 | "files": [
502 | "bootstrap.php"
503 | ]
504 | },
505 | "notification-url": "https://packagist.org/downloads/",
506 | "license": [
507 | "MIT"
508 | ],
509 | "authors": [
510 | {
511 | "name": "Nicolas Grekas",
512 | "email": "p@tchwork.com"
513 | },
514 | {
515 | "name": "Symfony Community",
516 | "homepage": "https://symfony.com/contributors"
517 | }
518 | ],
519 | "description": "Symfony polyfill for the Mbstring extension",
520 | "homepage": "https://symfony.com",
521 | "keywords": [
522 | "compatibility",
523 | "mbstring",
524 | "polyfill",
525 | "portable",
526 | "shim"
527 | ],
528 | "support": {
529 | "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.23.1"
530 | },
531 | "funding": [
532 | {
533 | "url": "https://symfony.com/sponsor",
534 | "type": "custom"
535 | },
536 | {
537 | "url": "https://github.com/fabpot",
538 | "type": "github"
539 | },
540 | {
541 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
542 | "type": "tidelift"
543 | }
544 | ],
545 | "time": "2021-05-27T12:26:48+00:00"
546 | },
547 | {
548 | "name": "symfony/polyfill-php73",
549 | "version": "v1.23.0",
550 | "source": {
551 | "type": "git",
552 | "url": "https://github.com/symfony/polyfill-php73.git",
553 | "reference": "fba8933c384d6476ab14fb7b8526e5287ca7e010"
554 | },
555 | "dist": {
556 | "type": "zip",
557 | "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/fba8933c384d6476ab14fb7b8526e5287ca7e010",
558 | "reference": "fba8933c384d6476ab14fb7b8526e5287ca7e010",
559 | "shasum": ""
560 | },
561 | "require": {
562 | "php": ">=7.1"
563 | },
564 | "type": "library",
565 | "extra": {
566 | "branch-alias": {
567 | "dev-main": "1.23-dev"
568 | },
569 | "thanks": {
570 | "name": "symfony/polyfill",
571 | "url": "https://github.com/symfony/polyfill"
572 | }
573 | },
574 | "autoload": {
575 | "psr-4": {
576 | "Symfony\\Polyfill\\Php73\\": ""
577 | },
578 | "files": [
579 | "bootstrap.php"
580 | ],
581 | "classmap": [
582 | "Resources/stubs"
583 | ]
584 | },
585 | "notification-url": "https://packagist.org/downloads/",
586 | "license": [
587 | "MIT"
588 | ],
589 | "authors": [
590 | {
591 | "name": "Nicolas Grekas",
592 | "email": "p@tchwork.com"
593 | },
594 | {
595 | "name": "Symfony Community",
596 | "homepage": "https://symfony.com/contributors"
597 | }
598 | ],
599 | "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions",
600 | "homepage": "https://symfony.com",
601 | "keywords": [
602 | "compatibility",
603 | "polyfill",
604 | "portable",
605 | "shim"
606 | ],
607 | "support": {
608 | "source": "https://github.com/symfony/polyfill-php73/tree/v1.23.0"
609 | },
610 | "funding": [
611 | {
612 | "url": "https://symfony.com/sponsor",
613 | "type": "custom"
614 | },
615 | {
616 | "url": "https://github.com/fabpot",
617 | "type": "github"
618 | },
619 | {
620 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
621 | "type": "tidelift"
622 | }
623 | ],
624 | "time": "2021-02-19T12:13:01+00:00"
625 | },
626 | {
627 | "name": "symfony/polyfill-php80",
628 | "version": "v1.23.1",
629 | "source": {
630 | "type": "git",
631 | "url": "https://github.com/symfony/polyfill-php80.git",
632 | "reference": "1100343ed1a92e3a38f9ae122fc0eb21602547be"
633 | },
634 | "dist": {
635 | "type": "zip",
636 | "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/1100343ed1a92e3a38f9ae122fc0eb21602547be",
637 | "reference": "1100343ed1a92e3a38f9ae122fc0eb21602547be",
638 | "shasum": ""
639 | },
640 | "require": {
641 | "php": ">=7.1"
642 | },
643 | "type": "library",
644 | "extra": {
645 | "branch-alias": {
646 | "dev-main": "1.23-dev"
647 | },
648 | "thanks": {
649 | "name": "symfony/polyfill",
650 | "url": "https://github.com/symfony/polyfill"
651 | }
652 | },
653 | "autoload": {
654 | "psr-4": {
655 | "Symfony\\Polyfill\\Php80\\": ""
656 | },
657 | "files": [
658 | "bootstrap.php"
659 | ],
660 | "classmap": [
661 | "Resources/stubs"
662 | ]
663 | },
664 | "notification-url": "https://packagist.org/downloads/",
665 | "license": [
666 | "MIT"
667 | ],
668 | "authors": [
669 | {
670 | "name": "Ion Bazan",
671 | "email": "ion.bazan@gmail.com"
672 | },
673 | {
674 | "name": "Nicolas Grekas",
675 | "email": "p@tchwork.com"
676 | },
677 | {
678 | "name": "Symfony Community",
679 | "homepage": "https://symfony.com/contributors"
680 | }
681 | ],
682 | "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions",
683 | "homepage": "https://symfony.com",
684 | "keywords": [
685 | "compatibility",
686 | "polyfill",
687 | "portable",
688 | "shim"
689 | ],
690 | "support": {
691 | "source": "https://github.com/symfony/polyfill-php80/tree/v1.23.1"
692 | },
693 | "funding": [
694 | {
695 | "url": "https://symfony.com/sponsor",
696 | "type": "custom"
697 | },
698 | {
699 | "url": "https://github.com/fabpot",
700 | "type": "github"
701 | },
702 | {
703 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
704 | "type": "tidelift"
705 | }
706 | ],
707 | "time": "2021-07-28T13:41:28+00:00"
708 | },
709 | {
710 | "name": "symfony/service-contracts",
711 | "version": "v2.4.0",
712 | "source": {
713 | "type": "git",
714 | "url": "https://github.com/symfony/service-contracts.git",
715 | "reference": "f040a30e04b57fbcc9c6cbcf4dbaa96bd318b9bb"
716 | },
717 | "dist": {
718 | "type": "zip",
719 | "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f040a30e04b57fbcc9c6cbcf4dbaa96bd318b9bb",
720 | "reference": "f040a30e04b57fbcc9c6cbcf4dbaa96bd318b9bb",
721 | "shasum": ""
722 | },
723 | "require": {
724 | "php": ">=7.2.5",
725 | "psr/container": "^1.1"
726 | },
727 | "suggest": {
728 | "symfony/service-implementation": ""
729 | },
730 | "type": "library",
731 | "extra": {
732 | "branch-alias": {
733 | "dev-main": "2.4-dev"
734 | },
735 | "thanks": {
736 | "name": "symfony/contracts",
737 | "url": "https://github.com/symfony/contracts"
738 | }
739 | },
740 | "autoload": {
741 | "psr-4": {
742 | "Symfony\\Contracts\\Service\\": ""
743 | }
744 | },
745 | "notification-url": "https://packagist.org/downloads/",
746 | "license": [
747 | "MIT"
748 | ],
749 | "authors": [
750 | {
751 | "name": "Nicolas Grekas",
752 | "email": "p@tchwork.com"
753 | },
754 | {
755 | "name": "Symfony Community",
756 | "homepage": "https://symfony.com/contributors"
757 | }
758 | ],
759 | "description": "Generic abstractions related to writing services",
760 | "homepage": "https://symfony.com",
761 | "keywords": [
762 | "abstractions",
763 | "contracts",
764 | "decoupling",
765 | "interfaces",
766 | "interoperability",
767 | "standards"
768 | ],
769 | "support": {
770 | "source": "https://github.com/symfony/service-contracts/tree/v2.4.0"
771 | },
772 | "funding": [
773 | {
774 | "url": "https://symfony.com/sponsor",
775 | "type": "custom"
776 | },
777 | {
778 | "url": "https://github.com/fabpot",
779 | "type": "github"
780 | },
781 | {
782 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
783 | "type": "tidelift"
784 | }
785 | ],
786 | "time": "2021-04-01T10:43:52+00:00"
787 | },
788 | {
789 | "name": "symfony/string",
790 | "version": "v5.3.7",
791 | "source": {
792 | "type": "git",
793 | "url": "https://github.com/symfony/string.git",
794 | "reference": "8d224396e28d30f81969f083a58763b8b9ceb0a5"
795 | },
796 | "dist": {
797 | "type": "zip",
798 | "url": "https://api.github.com/repos/symfony/string/zipball/8d224396e28d30f81969f083a58763b8b9ceb0a5",
799 | "reference": "8d224396e28d30f81969f083a58763b8b9ceb0a5",
800 | "shasum": ""
801 | },
802 | "require": {
803 | "php": ">=7.2.5",
804 | "symfony/polyfill-ctype": "~1.8",
805 | "symfony/polyfill-intl-grapheme": "~1.0",
806 | "symfony/polyfill-intl-normalizer": "~1.0",
807 | "symfony/polyfill-mbstring": "~1.0",
808 | "symfony/polyfill-php80": "~1.15"
809 | },
810 | "require-dev": {
811 | "symfony/error-handler": "^4.4|^5.0",
812 | "symfony/http-client": "^4.4|^5.0",
813 | "symfony/translation-contracts": "^1.1|^2",
814 | "symfony/var-exporter": "^4.4|^5.0"
815 | },
816 | "type": "library",
817 | "autoload": {
818 | "psr-4": {
819 | "Symfony\\Component\\String\\": ""
820 | },
821 | "files": [
822 | "Resources/functions.php"
823 | ],
824 | "exclude-from-classmap": [
825 | "/Tests/"
826 | ]
827 | },
828 | "notification-url": "https://packagist.org/downloads/",
829 | "license": [
830 | "MIT"
831 | ],
832 | "authors": [
833 | {
834 | "name": "Nicolas Grekas",
835 | "email": "p@tchwork.com"
836 | },
837 | {
838 | "name": "Symfony Community",
839 | "homepage": "https://symfony.com/contributors"
840 | }
841 | ],
842 | "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way",
843 | "homepage": "https://symfony.com",
844 | "keywords": [
845 | "grapheme",
846 | "i18n",
847 | "string",
848 | "unicode",
849 | "utf-8",
850 | "utf8"
851 | ],
852 | "support": {
853 | "source": "https://github.com/symfony/string/tree/v5.3.7"
854 | },
855 | "funding": [
856 | {
857 | "url": "https://symfony.com/sponsor",
858 | "type": "custom"
859 | },
860 | {
861 | "url": "https://github.com/fabpot",
862 | "type": "github"
863 | },
864 | {
865 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
866 | "type": "tidelift"
867 | }
868 | ],
869 | "time": "2021-08-26T08:00:08+00:00"
870 | }
871 | ],
872 | "packages-dev": [],
873 | "aliases": [],
874 | "minimum-stability": "stable",
875 | "stability-flags": [],
876 | "prefer-stable": false,
877 | "prefer-lowest": false,
878 | "platform": [],
879 | "platform-dev": [],
880 | "plugin-api-version": "2.1.0"
881 | }
882 |
--------------------------------------------------------------------------------