about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--doc/languages-frameworks/php.section.md45
-rw-r--r--nixos/doc/manual/release-notes/rl-2009.xml21
-rw-r--r--nixos/modules/services/mail/roundcube.nix2
-rw-r--r--nixos/modules/services/web-apps/nextcloud.nix4
-rw-r--r--pkgs/development/interpreters/php/default.nix41
5 files changed, 67 insertions, 46 deletions
diff --git a/doc/languages-frameworks/php.section.md b/doc/languages-frameworks/php.section.md
index a302a9a7f87d..31190f3b51a4 100644
--- a/doc/languages-frameworks/php.section.md
+++ b/doc/languages-frameworks/php.section.md
@@ -30,7 +30,7 @@ opcache extension shipped with PHP is available at
 `php.extensions.opcache` and the third-party ImageMagick extension at
 `php.extensions.imagick`.
 
-The different versions of PHP that nixpkgs provides is located under
+The different versions of PHP that nixpkgs provides are located under
 attributes named based on major and minor version number; e.g.,
 `php74` is PHP 7.4 with commonly used extensions installed,
 `php74base` is the same PHP runtime without extensions.
@@ -39,28 +39,31 @@ attributes named based on major and minor version number; e.g.,
 
 A PHP package with specific extensions enabled can be built using
 `php.withExtensions`. This is a function which accepts an anonymous
-function as its only argument; the function should take one argument,
-the set of all extensions, and return a list of wanted extensions. For
-example, a PHP package with the opcache and ImageMagick extensions
-enabled:
+function as its only argument; the function should accept two named
+parameters: `enabled` - a list of currently enabled extensions and
+`all` - the set of all extensions, and return a list of wanted
+extensions. For example, a PHP package with all default extensions and
+ImageMagick enabled:
 
 ```nix
-php.withExtensions (e: with e; [ imagick opcache ])
+php.withExtensions ({ enabled, all }:
+  enabled ++ [ all.imagick ])
 ```
 
-Note that this will give you a package with _only_ opcache and
-ImageMagick, none of the other extensions which are enabled by default
-in the `php` package will be available.
+To exclude some, but not all, of the default extensions, you can
+filter the `enabled` list like this:
 
-To enable building on a previous PHP package, the currently enabled
-extensions are made available in its `enabledExtensions`
-attribute. For example, to generate a package with all default
-extensions enabled, except opcache, but with ImageMagick:
+```nix
+php.withExtensions ({ enabled, all }:
+  (lib.filter (e: e != php.extensions.opcache) enabled)
+  ++ [ all.imagick ])
+```
+
+To build your list of extensions from the ground up, you can simply
+ignore `enabled`:
 
 ```nix
-php.withExtensions (e:
-  (lib.filter (e: e != php.extensions.opcache) php.enabledExtensions)
-  ++ [ e.imagick ])
+php.withExtensions ({ all, ... }: with all; [ opcache imagick ])
 ```
 
 If you want a PHP build with extra configuration in the `php.ini`
@@ -73,7 +76,7 @@ and ImageMagick extensions enabled, and `memory_limit` set to `256M`:
 
 ```nix
 php.buildEnv {
-  extensions = e: with e; [ imagick opcache ];
+  extensions = { all, ... }: with all; [ imagick opcache ];
   extraConfig = "memory_limit=256M";
 }
 ```
@@ -85,7 +88,7 @@ follows:
 
 ```nix
 let
-  myPhp = php.withExtensions (e: with e; [ imagick opcache ]);
+  myPhp = php.withExtensions ({ all, ... }: with all; [ opcache imagick ]);
 in {
   services.phpfpm.pools."foo".phpPackage = myPhp;
 };
@@ -94,7 +97,7 @@ in {
 ```nix
 let
   myPhp = php.buildEnv {
-    extensions = e: with e; [ imagick opcache ];
+    extensions = { all, ... }: with all; [ imagick opcache ];
     extraConfig = "memory_limit=256M";
   };
 in {
@@ -105,8 +108,8 @@ in {
 ##### Example usage with `nix-shell`
 
 This brings up a temporary environment that contains a PHP interpreter
-with the extensions `imagick` and `opcache` enabled.
+with the extensions `imagick` and `opcache` enabled:
 
 ```sh
-nix-shell -p 'php.buildEnv { extensions = e: with e; [ imagick opcache ]; }'
+nix-shell -p 'php.withExtensions ({ all, ... }: with all; [ imagick opcache ])'
 ```
diff --git a/nixos/doc/manual/release-notes/rl-2009.xml b/nixos/doc/manual/release-notes/rl-2009.xml
index 3e29c19af8fb..e4e44c8405f3 100644
--- a/nixos/doc/manual/release-notes/rl-2009.xml
+++ b/nixos/doc/manual/release-notes/rl-2009.xml
@@ -135,18 +135,23 @@
    </listitem>
    <listitem>
      <para>
-       Since this release there's an easy way to customize your PHP install to get a much smaller
-       base PHP with only wanted extensions enabled. See the following snippet installing a smaller PHP
-       with the extensions <literal>imagick</literal>, <literal>opcache</literal> and
+       Since this release there's an easy way to customize your PHP
+       install to get a much smaller base PHP with only wanted
+       extensions enabled. See the following snippet installing a
+       smaller PHP with the extensions <literal>imagick</literal>,
+       <literal>opcache</literal>, <literal>pdo</literal> and
        <literal>pdo_mysql</literal> loaded:
 
        <programlisting>
 environment.systemPackages = [
-(pkgs.php.buildEnv { extensions = pp: with pp; [
-    imagick
-    opcache
-    pdo_mysql
-  ]; })
+  (pkgs.php.withExtensions
+    ({ all, ... }: with all; [
+      imagick
+      opcache
+      pdo
+      pdo_mysql
+    ])
+  )
 ];</programlisting>
 
        The default <literal>php</literal> attribute hasn't lost any extensions -
diff --git a/nixos/modules/services/mail/roundcube.nix b/nixos/modules/services/mail/roundcube.nix
index 21e92cfee016..ed1439745ac9 100644
--- a/nixos/modules/services/mail/roundcube.nix
+++ b/nixos/modules/services/mail/roundcube.nix
@@ -7,7 +7,7 @@ let
   fpm = config.services.phpfpm.pools.roundcube;
   localDB = cfg.database.host == "localhost";
   user = cfg.database.username;
-  phpWithPspell = pkgs.php.withExtensions (e: [ e.pspell ] ++ pkgs.php.enabledExtensions);
+  phpWithPspell = pkgs.php.withExtensions ({ enabled, all }: [ all.pspell ] ++ enabled);
 in
 {
   options.services.roundcube = {
diff --git a/nixos/modules/services/web-apps/nextcloud.nix b/nixos/modules/services/web-apps/nextcloud.nix
index 5f6f2bc7a16d..f826096bf608 100644
--- a/nixos/modules/services/web-apps/nextcloud.nix
+++ b/nixos/modules/services/web-apps/nextcloud.nix
@@ -11,8 +11,8 @@ let
       base = pkgs.php74;
     in
       base.buildEnv {
-        extensions = e: with e;
-          base.enabledExtensions ++ [
+        extensions = { enabled, all }: with all;
+          enabled ++ [
             apcu redis memcached imagick
           ];
         extraConfig = phpOptionsStr;
diff --git a/pkgs/development/interpreters/php/default.nix b/pkgs/development/interpreters/php/default.nix
index c1a7cdd11c47..2313f9fbcc48 100644
--- a/pkgs/development/interpreters/php/default.nix
+++ b/pkgs/development/interpreters/php/default.nix
@@ -43,8 +43,16 @@ let
           phpWithExtensions = self.withExtensions defaultPhpExtensions;
         });
 
-        mkBuildEnv = prevArgs: lib.makeOverridable (
-          { extensions ? (_: []), extraConfig ? "", ... }@innerArgs:
+        # buildEnv wraps php to provide additional extensions and
+        # configuration. Its usage is documented in
+        # doc/languages-frameworks/php.section.md.
+        #
+        # Create a buildEnv with earlier overridden values and
+        # extensions functions in its closure. This is necessary for
+        # consecutive calls to buildEnv and overrides to work as
+        # expected.
+        mkBuildEnv = prevArgs: prevExtensionFunctions: lib.makeOverridable (
+          { extensions ? ({...}: []), extraConfig ? "", ... }@innerArgs:
             let
               allArgs = args // prevArgs // innerArgs;
               filteredArgs = builtins.removeAttrs allArgs [ "extensions" "extraConfig" ];
@@ -54,8 +62,15 @@ let
                 inherit php phpWithExtensions;
               });
 
+              allExtensionFunctions = prevExtensionFunctions ++ [ extensions ];
+              enabledExtensions =
+                builtins.foldl'
+                  (state: f:
+                    f { enabled = state; all = php-packages.extensions; })
+                  []
+                  allExtensionFunctions;
+
               getExtName = ext: lib.removePrefix "php-" (builtins.parseDrvName ext.name).name;
-              enabledExtensions = extensions php-packages.extensions;
 
               # Generate extension load configuration snippets from the
               # extension parameter. This is an attrset suitable for use
@@ -89,9 +104,8 @@ let
                 inherit (php) version;
                 nativeBuildInputs = [ makeWrapper ];
                 passthru = {
-                  buildEnv = mkBuildEnv allArgs;
-                  withExtensions = mkWithExtensions allArgs;
-                  inherit enabledExtensions;
+                  buildEnv = mkBuildEnv allArgs allExtensionFunctions;
+                  withExtensions = mkWithExtensions allArgs allExtensionFunctions;
                   inherit (php-packages) packages extensions;
                 };
                 paths = [ php ];
@@ -108,8 +122,8 @@ let
             in
               phpWithExtensions);
 
-        mkWithExtensions = prevArgs: extensions:
-          mkBuildEnv prevArgs { inherit extensions; };
+        mkWithExtensions = prevArgs: prevExtensionFunctions: extensions:
+          mkBuildEnv prevArgs prevExtensionFunctions { inherit extensions; };
 
         pcre' = if (lib.versionAtLeast version "7.3") then pcre2 else pcre;
       in
@@ -218,9 +232,8 @@ let
           outputs = [ "out" "dev" ];
 
           passthru = {
-            enabledExtensions = [];
-            buildEnv = mkBuildEnv {};
-            withExtensions = mkWithExtensions {};
+            buildEnv = mkBuildEnv {} [];
+            withExtensions = mkWithExtensions {} [];
             inherit (php-packages) packages extensions;
           };
 
@@ -258,7 +271,7 @@ let
     inherit defaultPhpExtensions;
   });
 
-  defaultPhpExtensions = extensions: with extensions; ([
+  defaultPhpExtensions = { all, ... }: with all; ([
     bcmath calendar curl ctype dom exif fileinfo filter ftp gd
     gettext gmp iconv intl json ldap mbstring mysqli mysqlnd opcache
     openssl pcntl pdo pdo_mysql pdo_odbc pdo_pgsql pdo_sqlite pgsql
@@ -266,8 +279,8 @@ let
     tokenizer xmlreader xmlwriter zip zlib
   ] ++ lib.optionals (!stdenv.isDarwin) [ imap ]);
 
-  defaultPhpExtensionsWithHash = extensions:
-    (defaultPhpExtensions extensions) ++ [ extensions.hash ];
+  defaultPhpExtensionsWithHash = { all, ... }:
+    (defaultPhpExtensions { inherit all; }) ++ [ all.hash ];
 
   php74 = php74base.withExtensions defaultPhpExtensions;
   php73 = php73base.withExtensions defaultPhpExtensionsWithHash;