Skip to content

Commit 8a7278d

Browse files
committed
feat: add support for .env configuration files and dotenv integration
1 parent 3ef0af5 commit 8a7278d

8 files changed

Lines changed: 156 additions & 77 deletions

File tree

.env.dist

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
# This file is a "template" of what your .env file should look like.
2+
# Set variables here that may be different on each deployment target of the app,
3+
# e.g. development, staging, production.
4+
#
5+
# On `composer install`/`composer update`, this file is copied to `.env` (unless
6+
# it already exists) and PHPLIST_SECRET is replaced with a freshly generated value.
7+
#
8+
# https://symfony.com/doc/current/configuration.html#configuring-environment-variables-in-env-files
9+
10+
PHPLIST_DATABASE_DRIVER=pdo_mysql
11+
PHPLIST_DATABASE_PATH=
12+
PHPLIST_DATABASE_HOST=127.0.0.1
13+
PHPLIST_DATABASE_PORT=3306
14+
PHPLIST_DATABASE_NAME=phplistdb
15+
PHPLIST_DATABASE_USER=phplist
16+
PHPLIST_DATABASE_PASSWORD=phplist
17+
DATABASE_PREFIX=phplist_
18+
LIST_TABLE_PREFIX=listattr_
19+
20+
APP_DEV_VERSION=0
21+
APP_DEV_EMAIL=dev@dev.com
22+
APP_POWERED_BY_PHPLIST=0
23+
PREFERENCEPAGE_SHOW_PRIVATE_LISTS=0
24+
25+
API_BASE_URL=http://api.phplist.local/
26+
FRONT_END_BASE_URL=http://frontend.phplist.local
27+
28+
parallel_use_with_phplist3=0
29+
30+
# Email configuration
31+
MAILER_FROM=noreply@phplist.com
32+
MAILER_DSN=null://null
33+
CONFIRMATION_URL=http://api.phplist.local/api/v2/subscriber/confirm/
34+
SUBSCRIPTION_CONFIRMATION_URL=http://api.phplist.local/api/v2/subscription/confirm/
35+
PASSWORD_RESET_URL=https://example.com/reset/
36+
SHOW_UNSUBSCRIBELINK=1
37+
38+
# Bounce email settings
39+
BOUNCE_EMAIL=bounce@phplist.com
40+
BOUNCE_IMAP_PASS=bounce@phplist.com
41+
BOUNCE_IMAP_HOST=imap.phplist.com
42+
BOUNCE_IMAP_PORT=993
43+
BOUNCE_IMAP_ENCRYPTION=ssl
44+
BOUNCE_IMAP_MAILBOX=/var/spool/mail/bounces
45+
BOUNCE_IMAP_MAILBOX_NAME=INBOX,ONE_MORE
46+
BOUNCE_IMAP_PROTOCOL=imap
47+
BOUNCE_IMAP_UNSUBSCRIBE_THRESHOLD=5
48+
BOUNCE_IMAP_BLACKLIST_THRESHOLD=3
49+
BOUNCE_IMAP_PURGE=0
50+
BOUNCE_IMAP_PURGE_UNPROCESSED=0
51+
52+
# Messenger configuration for asynchronous processing
53+
MESSENGER_TRANSPORT_DSN=doctrine://default?auto_setup=true
54+
55+
# A secret key that's used to generate certain security-related tokens
56+
PHPLIST_SECRET=%s
57+
VERIFY_SSL=1
58+
59+
APP_PHPLIST_ISP_CONF_PATH=/etc/phplist.conf
60+
61+
# Message sending
62+
MAILQUEUE_BATCH_SIZE=5
63+
MAILQUEUE_BATCH_PERIOD=5
64+
MAILQUEUE_THROTTLE=5
65+
MESSAGING_MAX_PROCESS_TIME=600
66+
MAX_MAILSIZE=209715200
67+
DEFAULT_MESSAGEAGE=691200
68+
USE_MANUAL_TEXT_PART=0
69+
MESSAGING_BLACKLIST_GRACE_TIME=600
70+
GOOGLE_SENDERID=
71+
USE_AMAZONSES=0
72+
USE_PRECEDENCE_HEADER=0
73+
EMBEDEXTERNALIMAGES=0
74+
EMBEDUPLOADIMAGES=0
75+
EXTERNALIMAGE_MAXAGE=0
76+
EXTERNALIMAGE_TIMEOUT=30
77+
EXTERNALIMAGE_MAXSIZE=204800
78+
FORWARD_ALTERNATIVE_CONTENT=0
79+
EMAILTEXTCREDITS=0
80+
ALWAYS_ADD_USERTRACK=1
81+
SEND_LISTADMIN_COPY=0
82+
83+
FORWARD_EMAIL_PERIOD="1 minute"
84+
FORWARD_EMAIL_COUNT=1
85+
FORWARD_PERSONAL_NOTE_SIZE=0
86+
FORWARD_FRIEND_COUNT_ATTRIBUTE=
87+
KEEPFORWARDERATTRIBUTES=0
88+
89+
UPLOADIMAGES_DIR=uploadimages
90+
PHPLIST_UPLOADS_MAX_SIZE=5M
91+
92+
PUBLIC_SCHEMA=https
93+
PHPLIST_ATTACHMENT_DOWNLOAD_URL=https://example.com/download/
94+
PHPLIST_ATTACHMENT_REPOSITORY_PATH=/tmp
95+
MAX_AVATAR_SIZE=100000

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
/config/bundles.yml
99
/config/config_modules.yml
1010
/config/parameters.yml
11+
/.env
12+
/.env.local
13+
/.env.*.local
1114
/config/routing_modules.yml
1215
/nbproject
1316
/var/

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@ This project adheres to [Semantic Versioning](https://semver.org/).
77

88
### Added
99
- Graylog integration for centralized logging (#TBD)
10+
- `symfony/dotenv` support: configuration values are now read from a `.env` file (generated from `.env.dist` on install/update), in addition to real environment variables (#TBD)
1011

1112
### Changed
13+
- `config/parameters.yml.dist` no longer contains inline `env(VAR): default` fallbacks; defaults now live in `.env.dist` (#TBD)
1214

1315
### Deprecated
1416

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ this code.
6363
The phpList application is configured so that the built-in PHP web server can
6464
run in development and testing mode, while Apache can run in production mode.
6565

66-
Please first set the database credentials in `config/parameters.yml`.
66+
Please first set the database credentials in `.env` (created from `.env.dist` on `composer install`/`composer update`).
6767

6868
### Development
6969

composer.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,8 @@
8787
"ext-fileinfo": "*",
8888
"setasign/fpdf": "^1.8",
8989
"phpdocumentor/reflection-docblock": "^5.2",
90-
"guzzlehttp/guzzle": "^7.4.5"
90+
"guzzlehttp/guzzle": "^7.4.5",
91+
"symfony/dotenv": "^6.4"
9192
},
9293
"require-dev": {
9394
"phpunit/phpunit": "^9.5",
@@ -127,6 +128,7 @@
127128
"PhpList\\Core\\Composer\\ScriptHandler::createGeneralConfiguration",
128129
"PhpList\\Core\\Composer\\ScriptHandler::createBundleConfiguration",
129130
"PhpList\\Core\\Composer\\ScriptHandler::createRoutesConfiguration",
131+
"PhpList\\Core\\Composer\\ScriptHandler::createDotenvConfiguration",
130132
"PhpList\\Core\\Composer\\ScriptHandler::createParametersConfiguration",
131133
"php bin/console cache:clear",
132134
"php bin/console cache:warmup"

config/parameters.yml.dist

Lines changed: 3 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -3,167 +3,97 @@
33
# https://symfony.com/doc/current/best_practices/configuration.html#infrastructure-related-configuration
44
#
55
# These variables are read from environment variables using the "env" construct.
6-
# You can set environment variables in the Apache host configuration and also on the command line.
7-
# If you cannot provide any environment variables, you can also set the variables in this file
8-
# in the lines with "env(VARIABLE_NAME)".
6+
# The environment variables themselves are defined in the ".env" file (see ".env.dist" for the template)
7+
# and/or in the actual environment (e.g. Apache host configuration, command line).
98
parameters:
109
database_driver: '%%env(PHPLIST_DATABASE_DRIVER)%%'
11-
env(PHPLIST_DATABASE_DRIVER): 'pdo_mysql'
1210
database_path: '%%env(PHPLIST_DATABASE_PATH)%%'
13-
env(PHPLIST_DATABASE_PATH): null
1411
database_host: '%%env(PHPLIST_DATABASE_HOST)%%'
15-
env(PHPLIST_DATABASE_HOST): '127.0.0.1'
1612
database_port: '%%env(PHPLIST_DATABASE_PORT)%%'
17-
env(PHPLIST_DATABASE_PORT): '3306'
1813
database_name: '%%env(PHPLIST_DATABASE_NAME)%%'
19-
env(PHPLIST_DATABASE_NAME): 'phplistdb'
2014
database_user: '%%env(PHPLIST_DATABASE_USER)%%'
21-
env(PHPLIST_DATABASE_USER): 'phplist'
2215
database_password: '%%env(PHPLIST_DATABASE_PASSWORD)%%'
23-
env(PHPLIST_DATABASE_PASSWORD): 'phplist'
2416
database_prefix: '%%env(DATABASE_PREFIX)%%'
25-
env(DATABASE_PREFIX): 'phplist_'
2617
list_table_prefix: '%%env(LIST_TABLE_PREFIX)%%'
27-
env(LIST_TABLE_PREFIX): 'listattr_'
2818
app.dev_version: '%%env(APP_DEV_VERSION)%%'
29-
env(APP_DEV_VERSION): '0'
3019
app.dev_email: '%%env(APP_DEV_EMAIL)%%'
31-
env(APP_DEV_EMAIL): 'dev@dev.com'
3220
app.powered_by_phplist: '%%env(APP_POWERED_BY_PHPLIST)%%'
33-
env(APP_POWERED_BY_PHPLIST): '0'
3421
app.preference_page_show_private_lists: '%%env(PREFERENCEPAGE_SHOW_PRIVATE_LISTS)%%'
35-
env(PREFERENCEPAGE_SHOW_PRIVATE_LISTS): '0'
3622

3723
app.rest_api_base_url: '%%env(API_BASE_URL)%%/api/v2'
3824
app.api_base_url: '%%env(API_BASE_URL)%%'
39-
env(API_BASE_URL): 'http://api.phplist.local/'
4025
app.frontend_base_url: '%%env(FRONT_END_BASE_URL)%%'
41-
env(FRONT_END_BASE_URL): 'http://frontend.phplist.local'
4226

4327
parallel_use_with_phplist3: '%%env(parallel_use_with_phplist3)%%'
44-
env(parallel_use_with_phplist3): '0'
4528

4629
# Email configuration
4730
app.mailer_from: '%%env(MAILER_FROM)%%'
48-
env(MAILER_FROM): 'noreply@phplist.com'
4931
app.mailer_dsn: '%%env(MAILER_DSN)%%'
50-
env(MAILER_DSN): 'null://null' # set local_domain on transport
5132
app.confirmation_url: '%%env(CONFIRMATION_URL)%%'
52-
env(CONFIRMATION_URL): 'http://api.phplist.local/api/v2/subscriber/confirm/'
5333
app.subscription_confirmation_url: '%%env(SUBSCRIPTION_CONFIRMATION_URL)%%'
54-
env(SUBSCRIPTION_CONFIRMATION_URL): 'http://api.phplist.local/api/v2/subscription/confirm/'
5534
app.password_reset_url: '%%env(PASSWORD_RESET_URL)%%'
56-
env(PASSWORD_RESET_URL): 'https://example.com/reset/'
5735
app.show_unsubscribe_link: '%%env(SHOW_UNSUBSCRIBELINK)%%'
58-
env(SHOW_UNSUBSCRIBELINK): '1'
5936

6037
# bounce email settings
6138
imap_bounce.email: '%%env(BOUNCE_EMAIL)%%'
62-
env(BOUNCE_EMAIL): 'bounce@phplist.com'
6339
imap_bounce.password: '%%env(BOUNCE_IMAP_PASS)%%'
64-
env(BOUNCE_IMAP_PASS): 'bounce@phplist.com'
6540
imap_bounce.host: '%%env(BOUNCE_IMAP_HOST)%%'
66-
env(BOUNCE_IMAP_HOST): 'imap.phplist.com'
6741
imap_bounce.port: '%%env(BOUNCE_IMAP_PORT)%%'
68-
env(BOUNCE_IMAP_PORT): '993'
6942
imap_bounce.encryption: '%%env(BOUNCE_IMAP_ENCRYPTION)%%'
70-
env(BOUNCE_IMAP_ENCRYPTION): 'ssl'
7143
imap_bounce.mailbox: '%%env(BOUNCE_IMAP_MAILBOX)%%'
72-
env(BOUNCE_IMAP_MAILBOX): '/var/spool/mail/bounces'
7344
imap_bounce.mailbox_name: '%%env(BOUNCE_IMAP_MAILBOX_NAME)%%'
74-
env(BOUNCE_IMAP_MAILBOX_NAME): 'INBOX,ONE_MORE'
7545
imap_bounce.protocol: '%%env(BOUNCE_IMAP_PROTOCOL)%%'
76-
env(BOUNCE_IMAP_PROTOCOL): 'imap'
7746
imap_bounce.unsubscribe_threshold: '%%env(BOUNCE_IMAP_UNSUBSCRIBE_THRESHOLD)%%'
78-
env(BOUNCE_IMAP_UNSUBSCRIBE_THRESHOLD): '5'
7947
imap_bounce.blacklist_threshold: '%%env(BOUNCE_IMAP_BLACKLIST_THRESHOLD)%%'
80-
env(BOUNCE_IMAP_BLACKLIST_THRESHOLD): '3'
8148
imap_bounce.purge: '%%env(BOUNCE_IMAP_PURGE)%%'
82-
env(BOUNCE_IMAP_PURGE): '0'
8349
imap_bounce.purge_unprocessed: '%%env(BOUNCE_IMAP_PURGE_UNPROCESSED)%%'
84-
env(BOUNCE_IMAP_PURGE_UNPROCESSED): '0'
8550

8651
# Messenger configuration for asynchronous processing
8752
app.messenger_transport_dsn: '%%env(MESSENGER_TRANSPORT_DSN)%%'
88-
env(MESSENGER_TRANSPORT_DSN): 'doctrine://default?auto_setup=true'
8953

9054
# A secret key that's used to generate certain security-related tokens
9155
secret: '%%env(PHPLIST_SECRET)%%'
92-
env(PHPLIST_SECRET): %1$s
9356
phplist.verify_ssl: '%%env(VERIFY_SSL)%%'
94-
env(VERIFY_SSL): '1'
9557

9658
graylog_host: 'graylog.phplist.local'
9759
graylog_port: 12201
9860

9961
app.phplist_isp_conf_path: '%%env(APP_PHPLIST_ISP_CONF_PATH)%%'
100-
env(APP_PHPLIST_ISP_CONF_PATH): '/etc/phplist.conf'
10162

10263
# Message sending
10364
messaging.mail_queue_batch_size: '%%env(MAILQUEUE_BATCH_SIZE)%%'
104-
env(MAILQUEUE_BATCH_SIZE): '5'
10565
messaging.mail_queue_period: '%%env(MAILQUEUE_BATCH_PERIOD)%%'
106-
env(MAILQUEUE_BATCH_PERIOD): '5'
10766
messaging.mail_queue_throttle: '%%env(MAILQUEUE_THROTTLE)%%'
108-
env(MAILQUEUE_THROTTLE): '5'
10967
messaging.max_process_time: '%%env(MESSAGING_MAX_PROCESS_TIME)%%'
110-
env(MESSAGING_MAX_PROCESS_TIME): '600'
11168
messaging.max_mail_size: '%%env(MAX_MAILSIZE)%%'
112-
env(MAX_MAILSIZE): '209715200'
11369
messaging.default_message_age: '%%env(DEFAULT_MESSAGEAGE)%%'
114-
env(DEFAULT_MESSAGEAGE): '691200'
11570
messaging.use_manual_text_part: '%%env(USE_MANUAL_TEXT_PART)%%'
116-
env(USE_MANUAL_TEXT_PART): '0'
11771
messaging.blacklist_grace_time: '%%env(MESSAGING_BLACKLIST_GRACE_TIME)%%'
118-
env(MESSAGING_BLACKLIST_GRACE_TIME): '600'
11972
messaging.google_sender_id: '%%env(GOOGLE_SENDERID)%%'
120-
env(GOOGLE_SENDERID): ''
12173
messaging.use_amazon_ses: '%%env(USE_AMAZONSES)%%'
122-
env(USE_AMAZONSES): '0'
12374
messaging.use_precedence_header: '%%env(USE_PRECEDENCE_HEADER)%%'
124-
env(USE_PRECEDENCE_HEADER): '0'
12575
messaging.embed_external_images: '%%env(EMBEDEXTERNALIMAGES)%%'
126-
env(EMBEDEXTERNALIMAGES): '0'
12776
messaging.embed_uploaded_images: '%%env(EMBEDUPLOADIMAGES)%%'
128-
env(EMBEDUPLOADIMAGES): '0'
12977
messaging.external_image_max_age: '%%env(EXTERNALIMAGE_MAXAGE)%%'
130-
env(EXTERNALIMAGE_MAXAGE): '0'
13178
messaging.external_image_timeout: '%%env(EXTERNALIMAGE_TIMEOUT)%%'
132-
env(EXTERNALIMAGE_TIMEOUT): '30'
13379
messaging.external_image_max_size: '%%env(EXTERNALIMAGE_MAXSIZE)%%'
134-
env(EXTERNALIMAGE_MAXSIZE): '204800'
13580
messaging.forward_alternative_content: '%%env(FORWARD_ALTERNATIVE_CONTENT)%%'
136-
env(FORWARD_ALTERNATIVE_CONTENT): '0'
13781
messaging.email_text_credits: '%%env(EMAILTEXTCREDITS)%%'
138-
env(EMAILTEXTCREDITS): '0'
13982
messaging.always_add_user_track: '%%env(ALWAYS_ADD_USERTRACK)%%'
140-
env(ALWAYS_ADD_USERTRACK): '1'
14183
messaging.send_list_admin_copy: '%%env(SEND_LISTADMIN_COPY)%%'
142-
env(SEND_LISTADMIN_COPY): '0'
14384

14485
phplist.forward_email_period: '%%env(FORWARD_EMAIL_PERIOD)%%'
145-
env(FORWARD_EMAIL_PERIOD): '1 minute'
14686
phplist.forward_email_count: '%%env(FORWARD_EMAIL_COUNT)%%'
147-
env(FORWARD_EMAIL_COUNT): '1'
14887
phplist.forward_personal_note_size: '%%env(FORWARD_PERSONAL_NOTE_SIZE)%%'
149-
env(FORWARD_PERSONAL_NOTE_SIZE): '0'
15088
phplist.forward_friend_count_attribute: '%%env(FORWARD_FRIEND_COUNT_ATTRIBUTE)%%'
151-
env(FORWARD_FRIEND_COUNT_ATTRIBUTE): ''
15289
phplist.keep_forwarded_attributes: '%%env(KEEPFORWARDERATTRIBUTES)%%'
153-
env(KEEPFORWARDERATTRIBUTES): '0'
15490

15591
phplist.upload_images_dir: '%%env(UPLOADIMAGES_DIR)%%'
156-
env(UPLOADIMAGES_DIR): 'uploadimages'
15792
phplist.uploads.allowed_mime_types: ['image/jpeg', 'image/png', 'image/gif', 'image/webp', 'image/svg+xml']
15893
phplist.uploads.allowed_extensions: ['jpg', 'jpeg', 'png', 'gif', 'webp', 'svg']
15994
phplist.uploads.max_size: '%%env(PHPLIST_UPLOADS_MAX_SIZE)%%'
160-
env(PHPLIST_UPLOADS_MAX_SIZE): '5M'
16195

16296
phplist.public_schema: '%%env(PUBLIC_SCHEMA)%%'
163-
env(PUBLIC_SCHEMA): 'https'
16497
phplist.attachment_download_url: '%%env(PHPLIST_ATTACHMENT_DOWNLOAD_URL)%%'
165-
env(PHPLIST_ATTACHMENT_DOWNLOAD_URL): 'https://example.com/download/'
16698
phplist.attachment_repository_path: '%%env(PHPLIST_ATTACHMENT_REPOSITORY_PATH)%%'
167-
env(PHPLIST_ATTACHMENT_REPOSITORY_PATH): '/tmp'
168-
phplist.max_avatar_size: '%%env(MAX_AVATAR_SIZE)%%'
169-
env(MAX_AVATAR_SIZE): '100000'
99+
phplist.max_avatar_size: '%%env(MAX_AVATAR_SIZE)%%'

src/Composer/ScriptHandler.php

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,16 @@ class ScriptHandler
4848
*/
4949
const PARAMETERS_TEMPLATE_FILE = '/config/parameters.yml.dist';
5050

51+
/**
52+
* @var string
53+
*/
54+
const DOTENV_FILE = '/.env';
55+
56+
/**
57+
* @var string
58+
*/
59+
const DOTENV_TEMPLATE_FILE = '/.env.dist';
60+
5161
/**
5262
* @return string absolute application root directory without the trailing slash
5363
*
@@ -277,12 +287,31 @@ public static function createParametersConfiguration(): void
277287
}
278288

279289
$templateFilePath = __DIR__ . '/../..' . static::PARAMETERS_TEMPLATE_FILE;
290+
$configuration = file_get_contents($templateFilePath);
291+
292+
self::createAndWriteFile($configurationFilePath, $configuration);
293+
}
294+
295+
/**
296+
* Creates the .env file (the environment variables consumed by the parameters configuration)
297+
* by copying it from .env.dist, generating a fresh app secret in the process.
298+
*
299+
* @return void
300+
*/
301+
public static function createDotenvConfiguration(): void
302+
{
303+
$dotenvFilePath = self::getApplicationRoot() . self::DOTENV_FILE;
304+
if (file_exists($dotenvFilePath)) {
305+
return;
306+
}
307+
308+
$templateFilePath = __DIR__ . '/../..' . static::DOTENV_TEMPLATE_FILE;
280309
$template = file_get_contents($templateFilePath);
281310

282311
$secret = bin2hex(random_bytes(20));
283312
$configuration = sprintf($template, $secret);
284313

285-
self::createAndWriteFile($configurationFilePath, $configuration);
314+
self::createAndWriteFile($dotenvFilePath, $configuration);
286315
}
287316

288317
/**

0 commit comments

Comments
 (0)