Skip to content

Commit

Permalink
feat: introduce next generation PHP client surface (#612)
Browse files Browse the repository at this point in the history
Co-authored-by: David Supplee <dwsupplee@gmail.com>
Co-authored-by: Brent Shaffer <betterbrent@google.com>
Co-authored-by: Saransh Dhingra <saranshdhingra@google.com>
  • Loading branch information
4 people committed May 1, 2023
1 parent eea8eaf commit c675c3d
Show file tree
Hide file tree
Showing 279 changed files with 14,375 additions and 1,490 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ bazel-*
.php_cs.cache
composer.lock
.php-cs-fixer.cache
.phpunit.result.cache

# Vim
*.sw*
Expand Down
8 changes: 5 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"autoload": {
"psr-4": {
"Google\\PostProcessor\\": "src/PostProcessor",
"Google\\Generator\\": "src",
"Google\\Generator\\Tests\\": "tests",
"Google\\": "generated/Google",
Expand All @@ -27,14 +28,15 @@
}
},
"require": {
"php": "^7.4 || ^8.0",
"php": "^8.1",
"google/protobuf": "^3.18",
"friendsofphp/php-cs-fixer": "^3",
"symfony/yaml": "^5.2",
"symplify/coding-standard": "9.3.26"
"symplify/coding-standard": "9.3.26",
"microsoft/tolerant-php-parser": "^0.1.2"
},
"require-dev": {
"phpunit/phpunit": "^9.5",
"google/gax": "^1.17"
"google/gax": "^1.19.1"
}
}
22 changes: 22 additions & 0 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
bootstrap="tests/Unit/autoload.php"
colors="true"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd"
>
<coverage>
<include>
<directory suffix=".php">*/src</directory>
<directory suffix=".php">src</directory>
</include>
</coverage>
<testsuites>
<testsuite name="Unit Tests">
<directory>./tests/Unit</directory>
</testsuite>
</testsuites>
<php>
<ini name="memory_limit" value="2048M"/>
</php>
</phpunit>
9 changes: 6 additions & 3 deletions repositories.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,15 @@ def gapic_generator_php_repositories():
urls = ["https://github.com/googleapis/rules_gapic/archive/v%s.tar.gz" % _rules_gapic_version],
)

_php_version = "8.1.13"
maybe(
php,
name = "php_micro",
prebuilt_phps = ["@gapic_generator_php//:rules_php_gapic/resources/php-7.4.15_linux_x86_64.tar.gz"],
urls = ["https://www.php.net/distributions/php-7.4.15.tar.gz"],
strip_prefix = "php-7.4.15",
prebuilt_phps = [
"@gapic_generator_php//:rules_php_gapic/resources/php-%s_linux_x86_64.tar.gz" % _php_version,
],
urls = ["https://www.php.net/distributions/php-%s.tar.gz" % _php_version ],
strip_prefix = "php-%s" % _php_version,
)
maybe(
php_composer_install,
Expand Down
8 changes: 8 additions & 0 deletions rules_php_gapic/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,11 @@ php_binary(
visibility = ["//visibility:public"],
working_directory_flag_name = "side_loaded_root_dir",
)

php_binary(
name = "php_post_processor_binary",
entry_point = "src/PostProcessor/Main.php",
php_composer_install = "@php_gapic_generator_composer_install//:install",
visibility = ["//visibility:public"],
working_directory_flag_name = "base_dir",
)
10 changes: 6 additions & 4 deletions rules_php_gapic/php.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@
# limitations under the License.

def _php_binary_impl(ctx):
run_name = "{}_run.sh".format(ctx.attr.name)
out_dir = ctx.actions.declare_directory("out")
out_run_sh = ctx.actions.declare_file("run.sh")
out_run_sh = ctx.actions.declare_file(run_name)
entry_point_relative = ctx.file.entry_point.path[len(ctx.attr.entry_point.label.workspace_root):].strip("/")

# I don't understand why this is required:
Expand Down Expand Up @@ -59,14 +60,15 @@ tar cf - --dereference src/ generated/ googleapis/ tools/ vendor/ composer.json
working_directory_flag = ""
run_sh = """#!/bin/bash
WD="$(pwd)"
PHP="$WD/$(dirname $0)/run.sh.runfiles/$(basename $WD)/{php_short_path}"
cd "$(dirname $0)/run.sh.runfiles/$(basename $WD)/{out_short_path}/install"
"$PHP" -n -d memory_limit=512M './{entry_point}' {working_directory_flag}
PHP="$WD/$(dirname $0)/{run_name}.runfiles/$(basename $WD)/{php_short_path}"
cd "$(dirname $0)/{run_name}.runfiles/$(basename $WD)/{out_short_path}/install"
"$PHP" -n -d memory_limit=512M './{entry_point}' {working_directory_flag} $@
""".format(
php_short_path = ctx.file.php.short_path,
out_short_path = out_dir.short_path,
entry_point = entry_point_relative,
working_directory_flag = working_directory_flag,
run_name = run_name,
)
ctx.actions.write(out_run_sh, run_sh, is_executable = True)
return [DefaultInfo(
Expand Down
3 changes: 3 additions & 0 deletions rules_php_gapic/php_gapic.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ def php_gapic_srcjar(
transport = None,
rest_numeric_enums = False,
generate_snippets = True,
# Supported values validated and specified in src/Utils/MigrationMode.php.
migration_mode = "PRE_MIGRATION_SURFACE_ONLY",
generator_binary = Label("//rules_php_gapic:php_gapic_generator_binary"),
**kwargs):
plugin_file_args = {}
Expand All @@ -75,6 +77,7 @@ def php_gapic_srcjar(
# Set plugin arguments.
plugin_args = ["metadata"] # Generate the gapic_metadata.json file.
plugin_args.append("transport=%s" % transport)
plugin_args.append("migration-mode=%s" % migration_mode)

# Generate REGAPIC param for requesting response enums be JSON-encoded as numbers, not strings.
if rest_numeric_enums:
Expand Down
12 changes: 11 additions & 1 deletion rules_php_gapic/php_gapic_pkg.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ def _php_gapic_src_pkg_impl(ctx):
paths = _construct_package_dir_paths(ctx.attr.package_dir, ctx.outputs.pkg, ctx.label.name)

script = """
set -e
for proto_grpc_src in {proto_grpc_srcs}; do
mkdir -p {package_dir_path}/proto/src
unzip -q -o $proto_grpc_src -d {package_dir_path}/proto/src
Expand All @@ -60,8 +61,9 @@ def _php_gapic_src_pkg_impl(ctx):
mkdir -p {package_dir_path}/proto
unzip -q -o $gapic_src -d {package_dir_path}
done
{post_processor} --input {package_dir_path}
cd {package_dir_path}/{tar_cd_suffix}
tar -zchpf {tar_prefix}/{package_dir}.tar.gz {tar_prefix}/*
tar --exclude=*.build.txt -zchpf {tar_prefix}/{package_dir}.tar.gz {tar_prefix}/*
cd -
mv {package_dir_path}/{package_dir}.tar.gz {pkg}
rm -rf {package_dir_path}
Expand All @@ -73,19 +75,27 @@ def _php_gapic_src_pkg_impl(ctx):
pkg = ctx.outputs.pkg.path,
tar_cd_suffix = paths.tar_cd_suffix,
tar_prefix = paths.tar_prefix,
post_processor = ctx.executable._post_processor.path,
)

ctx.actions.run_shell(
inputs = proto_grpc_srcs + gapic_srcs,
command = script,
outputs = [ctx.outputs.pkg],
tools = [ctx.executable._post_processor],
)

_php_gapic_src_pkg = rule(
implementation = _php_gapic_src_pkg_impl,
attrs = {
"deps": attr.label_list(allow_files = True, mandatory = True),
"package_dir": attr.string(mandatory = True),
"_post_processor": attr.label(
executable = True,
mandatory = False,
default = Label("//rules_php_gapic:php_post_processor_binary"),
cfg = "exec",
)
},
outputs = {"pkg": "%{name}.tar.gz"},
)
Expand Down
Binary file not shown.
14 changes: 7 additions & 7 deletions rules_php_gapic/resources/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@ The recommended (tested) way of doing it is as follows:
```
3. Download the specific PHP distribution sources from https://www.php.net/distributions:
```
curl https://www.php.net/distributions/php-7.4.15.tar.gz -o php-7.4.15.tar.gz
curl https://www.php.net/distributions/php-8.1.13.tar.gz -o php-8.1.13.tar.gz
```
4. Unpack the downloaded archive:
```
tar -xzpf php-7.4.15.tar.gz
tar -xzpf php-8.1.13.tar.gz
```
5. Go to the unpacked directory:
```
cd php-7.4.15
cd php-8.1.13
```
6. Run the build config:
```
Expand All @@ -44,9 +44,9 @@ The recommended (tested) way of doing it is as follows:
--disable-mbregex \
--with-openssl \
--enable-bcmath \
--prefix=/tmp/php-7.4.15
--prefix=/tmp/php-8.1.13
```
Please make sure that the `--prefix` destination folder has the same name as the root folder of your unpacked archive (i.e. the one you `cd` in step 3; it is usually `php-<version>`, e.g. `php-7.4.15`).
Please make sure that the `--prefix` destination folder has the same name as the root folder of your unpacked archive (i.e. the one you `cd` in step 3; it is usually `php-<version>`, e.g. `php-8.1.13`).
7. Run the build:
```
make -j10
Expand All @@ -60,9 +60,9 @@ The recommended (tested) way of doing it is as follows:
```
cd /tmp
```
10. Pack the relevant binaries in the archive, using `php-<version>_platform.tar.gz` name format:
10. Pack the relevant binaries in the archive, using `php-<version>_<platform>.tar.gz` name format:
```
tar -zchpf php-7.4.15_linux_x86_64.tar.gz php-7.4.15/bin php-7.4.15/lib
tar -zchpf php-8.1.13_linux_x86_64.tar.gz php-8.1.13/bin php-8.1.13/lib
```
11. Copy the created archive to the `rules_gapic/php/resources` folder in this repository and post a PR.

Expand Down
1 change: 1 addition & 0 deletions rules_php_test/integration_test.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ def _php_overwrite_golden_impl(ctx):
golden_update_script_content = """
cd ${{BUILD_WORKSPACE_DIRECTORY}}
# Filename pattern-based removal is needed to preserve the BUILD.bazel file.
find tests/Integration/goldens/{api_name}/ -name \\*.txt -type f -delete
find tests/Integration/goldens/{api_name}/ -name \\*.php -type f -delete
find tests/Integration/goldens/{api_name}/ -name \\*.json -type f -delete
unzip -ao {goldens_output_zip} -d tests/Integration/goldens/{api_name}
Expand Down
67 changes: 61 additions & 6 deletions src/Ast/AST.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ abstract class AST
/** @var string Constant to reference `__DIR__`. */
public const __DIR__ = "\0__DIR__";

/** @var string Constant to reference `__CLASS__`. */
public const __CLASS__ = "\0__CLASS__";

/** @var string Constant to reference `isset`. */
public const ISSET = "\0isset";

Expand All @@ -56,12 +59,27 @@ abstract class AST
/** @var string Constant to reference `array_merge`. */
public const ARRAY_MERGE = "\0array_merge";

/** @var string Constant to reference `array_unshift`. */
public const ARRAY_UNSHIFT = "\0array_unshift";

/** @var string Constant to reference `call_user_func_array`. */
public const CALL_USER_FUNC_ARRAY = "\0call_user_func_array";

/** @var string Constant to reference `preg_match`. */
public const PREG_MATCH = "\0preg_match";

/** @var string Constant to reference `printf`. */
public const PRINT_F = "\0printf";

/** @var string Constant to reference `substr`. */
public const SUBSTR = "\0substr";

/** @var string Constant to reference `trigger_error`. */
public const TRIGGER_ERROR = "\0trigger_error";

/** @var string Constant to reference `E_USER_ERROR`. */
public const E_USER_ERROR = "\0E_USER_ERROR";

protected static function deref($obj): string
{
return $obj === static::SELF || $obj instanceof ResolvedType ? '::' : '->';
Expand Down Expand Up @@ -134,12 +152,18 @@ public static function file(?PhpClass $class): PhpFile
*
* @param Type $type The type of the class to create.
* @param ?ResolvedType $extends
* @param bool $final Flag indicating if the class is final or not.
* @param bool $abstract Flag indicating if the class is abtract or not.
*
* @return PhpClass
*/
public static function class(Type $type, ?ResolvedType $extends = null): PhpClass
{
return new PhpClass($type, $extends);
public static function class(
Type $type,
?ResolvedType $extends = null,
bool $final = false,
bool $abstract = false
): PhpClass {
return new PhpClass($type, $extends, $final, $abstract);
}

/**
Expand Down Expand Up @@ -360,10 +384,11 @@ public function toCode(): string
*
* @param mixed $data The array content. Supports both associative and sequential arrays.
* May be an array or a Map.
* @param bool $oneLine Indicates the code should be generated on one line, rather than multiple.
*
* @return Expression
*/
public static function array($data): Expression
public static function array(mixed $data, bool $oneLine = false): Expression
{
if (is_array($data)) {
$keyValues = Vector::new(array_map(fn ($v, $k) => [$k, $v], $data, array_keys($data)))
Expand All @@ -373,10 +398,11 @@ public static function array($data): Expression
} else {
throw new \Exception('$data must be an array or a Map.');
}
return new class($keyValues) extends Expression {
public function __construct($keyValues)
return new class($keyValues, $oneLine) extends Expression {
public function __construct($keyValues, $oneLine)
{
$this->keyValues = $keyValues;
$this->oneLine = $oneLine;
}
public function toCode(): string
{
Expand All @@ -387,6 +413,11 @@ public function toCode(): string
if (count($items) === 1 && substr($items[0], 0, 4) === 'new ') {
return "{$items}";
}
if ($this->oneLine) {
$itemsStr = $items->skipLast(1)->map(fn ($x) => "{$x}, ")->join();
$itemsStr = $itemsStr . "{$items->last()}";
return "[{$itemsStr}]";
}
$itemsStr = $items->map(fn ($x) => "{$x},\n")->join();
$firstNl = count($items) === 0 ? '' : "\n";
return "[{$firstNl}{$itemsStr}]";
Expand Down Expand Up @@ -728,6 +759,30 @@ public function toCode(): string
};
}

/**
* Create a '??' expression.
*
* @param Expression $expr The expression to check \isset and !\is_null, as well as the value to return if true.
* @param Expression $false The expresion to return if $expr is not set or is null.
*
* @return Expression
*/
public static function nullCoalescing(Expression $expr, Expression $false): Expression
{
return new class($expr, $false) extends Expression {
public function __construct($expr, $false)
{
$this->expr = $expr;
$this->false = $false;
}
public function toCode(): string
{
return static::toPhp($this->expr) .
' ?? ' . static::toPhp($this->false);
}
};
}

/**
* Create a while statement. This method returns a callable into which the loop code is passed.
*
Expand Down
2 changes: 1 addition & 1 deletion src/Ast/Expression.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public function offsetExists($offset): bool
return true;
}

public function offsetGet($offset)
public function offsetGet(mixed $offset): mixed
{
return AST::index($this, $offset);
}
Expand Down
Loading

0 comments on commit c675c3d

Please sign in to comment.