about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPol Dellaiera <pol.dellaiera@protonmail.com>2024-05-16 16:45:26 +0200
committerGitHub <noreply@github.com>2024-05-16 16:45:26 +0200
commit2ca9ba37bc17ba5c8d593cc203c0a4a0fe093e89 (patch)
treed65a7df618848d763390f818c52ce2c97ce594d5
parent68392decde7a0f9319843d2db698bec12c9fca6d (diff)
parent083f211783cad8ac7463e5a395dac4aceedf193a (diff)
Merge pull request #311299 from thenhnn/filesender-packaging-php-format
pkgs/formats: add generator for PHP config files
-rw-r--r--nixos/doc/manual/development/settings-options.section.md21
-rw-r--r--pkgs/pkgs-lib/formats.nix2
-rw-r--r--pkgs/pkgs-lib/formats/php/default.nix69
-rw-r--r--pkgs/pkgs-lib/tests/formats.nix44
4 files changed, 136 insertions, 0 deletions
diff --git a/nixos/doc/manual/development/settings-options.section.md b/nixos/doc/manual/development/settings-options.section.md
index 806eee5637907..cedc82d32f89a 100644
--- a/nixos/doc/manual/development/settings-options.section.md
+++ b/nixos/doc/manual/development/settings-options.section.md
@@ -146,6 +146,27 @@ have a predefined type and string generator already declared under
     :   Outputs the given attribute set as an Elixir map, instead of the
         default Elixir keyword list
 
+`pkgs.formats.php { finalVariable }` []{#pkgs-formats-php}
+
+:   A function taking an attribute set with values
+
+    `finalVariable`
+
+    :   The variable that will store generated expression (usually `config`). If set to `null`, generated expression will contain `return`.
+
+    It returns a set with PHP-Config-specific attributes `type`, `lib`, and
+    `generate` as specified [below](#pkgs-formats-result).
+
+    The `lib` attribute contains functions to be used in settings, for
+    generating special PHP values:
+
+    `mkRaw phpCode`
+
+    :   Outputs the given string as raw PHP code
+
+    `mkMixedArray list set`
+
+    :   Creates PHP array that contains both indexed and associative values. For example, `lib.mkMixedArray [ "hello" "world" ] { "nix" = "is-great"; }` returns `['hello', 'world', 'nix' => 'is-great']`
 
 []{#pkgs-formats-result}
 These functions all return an attribute set with these values:
diff --git a/pkgs/pkgs-lib/formats.nix b/pkgs/pkgs-lib/formats.nix
index 1b72270b43ca4..7cc0bf4f4e504 100644
--- a/pkgs/pkgs-lib/formats.nix
+++ b/pkgs/pkgs-lib/formats.nix
@@ -43,6 +43,8 @@ rec {
 
   hocon = (import ./formats/hocon/default.nix { inherit lib pkgs; }).format;
 
+  php = (import ./formats/php/default.nix { inherit lib pkgs; }).format;
+
   json = {}: {
 
     type = with lib.types; let
diff --git a/pkgs/pkgs-lib/formats/php/default.nix b/pkgs/pkgs-lib/formats/php/default.nix
new file mode 100644
index 0000000000000..9bd1de958d0be
--- /dev/null
+++ b/pkgs/pkgs-lib/formats/php/default.nix
@@ -0,0 +1,69 @@
+{pkgs, lib}: {
+  # Format for defining configuration of some PHP services, that use "include 'config.php';" approach.
+  format = {finalVariable ? null}: let
+    toPHP = value: {
+        "null" = "null";
+        "bool" = if value then "true" else "false";
+        "int" = toString value;
+        "float" = toString value;
+        "string" = string value;
+        "set" = attrs value;
+        "list" = list value;
+      }
+      .${builtins.typeOf value} or
+        (abort "should never happen: unknown value type ${builtins.typeOf value}");
+
+    # https://www.php.net/manual/en/language.types.string.php#language.types.string.syntax.single
+    escapeSingleQuotedString = lib.escape [ "'" "\\" ];
+    string = value: "'${escapeSingleQuotedString value}'";
+
+    listContent = values: lib.concatStringsSep ", " (map toPHP values);
+    list = values: "[" + (listContent values) + "]";
+
+    attrsContent = values: lib.pipe values [
+      (lib.mapAttrsToList (k: v: "${toPHP k} => ${toPHP v}"))
+      (lib.concatStringsSep ", ")
+    ];
+    attrs = set:
+      if set ? _phpType then specialType set
+      else
+          "[" + attrsContent set + "]";
+
+    mixedArray = {list, set}: if list == [] then attrs set else "[${listContent list}, ${attrsContent set}]";
+
+    specialType = {value, _phpType}: {
+      "mixed_array" = mixedArray value;
+      "raw" = value;
+    }.${_phpType};
+
+    type = with lib.types;
+      nullOr (oneOf [
+        bool
+        int
+        float
+        str
+        (attrsOf type)
+        (listOf type)
+      ])
+      // {
+        description = "PHP value";
+      };
+  in {
+
+    inherit type;
+
+    lib = {
+      mkMixedArray = list: set: {_phpType = "mixed_array"; value = { inherit list set;}; };
+      mkRaw = raw: {_phpType = "raw"; value = raw;};
+    };
+
+    generate = name: value: pkgs.writeTextFile {
+      inherit name;
+      text = let
+        # strict_types enabled here to easily debug problems when calling functions of incorrect type using `mkRaw`.
+        phpHeader = "<?php\ndeclare(strict_types=1);\n";
+      in if finalVariable == null then phpHeader + "return ${toPHP value};\n" else phpHeader + "\$${finalVariable} = ${toPHP value};\n";
+    };
+
+  };
+}
diff --git a/pkgs/pkgs-lib/tests/formats.nix b/pkgs/pkgs-lib/tests/formats.nix
index 3243f4058e680..86a35c6bf26dc 100644
--- a/pkgs/pkgs-lib/tests/formats.nix
+++ b/pkgs/pkgs-lib/tests/formats.nix
@@ -425,4 +425,48 @@ in runBuildTests {
       \u0627\u0644\u062c\u0628\u0631 = \u0623\u0643\u062b\u0631 \u0645\u0646 \u0645\u062c\u0631\u062f \u0623\u0631\u0642\u0627\u0645
     '';
   };
+
+  phpAtoms = shouldPass rec {
+    format = formats.php { finalVariable = "config"; };
+    input = {
+      null = null;
+      false = false;
+      true = true;
+      int = 10;
+      float = 3.141;
+      str = "foo";
+      str_special = "foo\ntesthello'''";
+      attrs.foo = null;
+      list = [ null null ];
+      mixed = format.lib.mkMixedArray [ 10 3.141 ] {
+        str = "foo";
+        attrs.foo = null;
+      };
+      raw = format.lib.mkRaw "random_function()";
+    };
+    expected = ''
+      <?php
+      declare(strict_types=1);
+      $config = ['attrs' => ['foo' => null], 'false' => false, 'float' => 3.141000, 'int' => 10, 'list' => [null, null], 'mixed' => [10, 3.141000, 'attrs' => ['foo' => null], 'str' => 'foo'], 'null' => null, 'raw' => random_function(), 'str' => 'foo', 'str_special' => 'foo
+      testhello\'\'\'${"'"}, 'true' => true];
+    '';
+  };
+
+  phpReturn = shouldPass {
+    format = formats.php { };
+    input = {
+      int = 10;
+      float = 3.141;
+      str = "foo";
+      str_special = "foo\ntesthello'''";
+      attrs.foo = null;
+    };
+    expected = ''
+      <?php
+      declare(strict_types=1);
+      return ['attrs' => ['foo' => null], 'float' => 3.141000, 'int' => 10, 'str' => 'foo', 'str_special' => 'foo
+      testhello\'\'\'${"'"}];
+    '';
+  };
+
 }