Skip to content

Commit 2f983df

Browse files
klimslimamelekhovets-sugarcrm
authored andcommitted
[BR-11210] – Sugar shadow extension does not work properly after Rector scan
PHPStan uses custom 'file' stream wrapper to capture loaded code, this unregisters shadow wrapper and breaks everything. To handle this, an option has been added to force the wrapper reinitialization
1 parent 5cc8f8f commit 2f983df

File tree

6 files changed

+59
-27
lines changed

6 files changed

+59
-27
lines changed

Dockerfile

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,16 @@ ARG PHP_BUILD_DIR=/var/task
44
ARG PHP_CONF_DIR=/etc/php.d
55
ARG PHP_EXT_DIR=/usr/lib64/php/modules
66

7+
RUN yum install -y amazon-linux-extras
8+
RUN amazon-linux-extras enable php8.2
9+
RUN amazon-linux-extras install -y php8.2
710
RUN yum clean all && \
811
yum -y upgrade && \
9-
yum -y install ilibzip-dev libonig-dev putils \
10-
yum -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm \
11-
https://rpms.remirepo.net/enterprise/remi-release-7.rpm \
12-
re2c \
13-
yum-utils && \
14-
yum-config-manager --disable remi-safe
12+
yum -y install ilibzip-dev libonig-dev putils gcc make \
13+
yum -y re2c \
14+
yum-utils
1515

16-
RUN yum-config-manager --enable remi-php82 && \
17-
yum-config-manager --setopt=remi-php82.priority=10 --save && \
18-
yum -y install php-cli php-common php-devel && \
16+
RUN yum -y install php-cli php-common php-devel && \
1917
yum clean all
2018

2119
#Extension install
@@ -38,7 +36,8 @@ RUN cd shadow && \
3836
./configure && \
3937
make && \
4038
make install && \
41-
make test && \
4239
echo "extension=${PHP_EXT_DIR}/shadow.so" > ${PHP_CONF_DIR}/shadow.ini
40+
RUN cd shadow && \
41+
php run-tests.php --show-diff .
4342

44-
ENTRYPOINT ["php", "-m"]
43+
ENTRYPOINT ["tail", "-f", "/dev/null"]

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,15 @@ Shadow function
3535
Shadow has one main function:
3636

3737
```c
38-
void shadow(string template, string instance[, array instance_only])
38+
void shadow(string template, string instance[, array instance_only, bool force = false])
3939
```
4040
4141
- template is the template directory
4242
- instance is instance directory
4343
- instance\_only is an array of directories or filenames (relative to
4444
instance directory) that are instance-only
45+
- force stream wrapper initialization (normally performed at request
46+
initialization, but in some cases should be done separately)
4547
4648
Other functions:
4749

php_shadow.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ ZEND_END_MODULE_GLOBALS(shadow)
6969
#define SHADOW_G(v) (shadow_globals.v)
7070
#endif
7171

72-
#define SHADOW_VERSION "1.1.1"
72+
#define SHADOW_VERSION "1.2.0"
7373

7474
ZEND_EXTERN_MODULE_GLOBALS(shadow)
7575

shadow.c

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ php_stream_wrapper shadow_wrapper = {
4848
static ssize_t shadow_dirstream_read(php_stream *stream, char *buf, size_t count);
4949
static int shadow_dirstream_close(php_stream *stream, int close_handle);
5050
static int shadow_dirstream_rewind(php_stream *stream, off_t offset, int whence, off_t *newoffs);
51+
static void shadow_init_wrapper();
5152

5253
static php_stream_ops shadow_dirstream_ops = {
5354
NULL,
@@ -423,22 +424,26 @@ PHP_MSHUTDOWN_FUNCTION(shadow)
423424
*/
424425
PHP_RINIT_FUNCTION(shadow)
425426
{
426-
if(SHADOW_G(enabled)) {
427-
zend_string *protocol;
428-
protocol = zend_string_init("file", strlen("file"), 0);
429-
php_unregister_url_stream_wrapper_volatile(protocol);
430-
php_register_url_stream_wrapper_volatile(protocol, &shadow_wrapper);
431-
zend_string_release_ex(protocol, 0);
432-
}
433-
SHADOW_G(template) = NULL;
434-
SHADOW_G(instance) = NULL;
435-
SHADOW_G(curdir) = NULL;
436-
SHADOW_G(segment_id) = 0;
437-
SHADOW_G(shadow_override_copy) = NULL;
427+
shadow_init_wrapper();
438428
return SUCCESS;
439429
}
440430
/* }}} */
441431

432+
static void shadow_init_wrapper() {
433+
if(SHADOW_G(enabled)) {
434+
zend_string *protocol;
435+
protocol = zend_string_init("file", strlen("file"), 0);
436+
php_unregister_url_stream_wrapper_volatile(protocol);
437+
php_register_url_stream_wrapper_volatile(protocol, &shadow_wrapper);
438+
zend_string_release_ex(protocol, 0);
439+
}
440+
SHADOW_G(template) = NULL;
441+
SHADOW_G(instance) = NULL;
442+
SHADOW_G(curdir) = NULL;
443+
SHADOW_G(segment_id) = 0;
444+
SHADOW_G(shadow_override_copy) = NULL;
445+
}
446+
442447
static void shadow_free_data()
443448
{
444449
if(SHADOW_G(template)) {
@@ -493,16 +498,21 @@ PHP_FUNCTION(shadow)
493498
char *temp = NULL;
494499
char *inst = NULL;
495500
size_t temp_len, inst_len;
501+
zend_bool force = 0; // New parameter
496502
HashTable *instance_only = NULL; /* paths relative to template root */
497503

498-
if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss|h", &temp, &temp_len, &inst, &inst_len, &instance_only) == FAILURE) {
504+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss|hb", &temp, &temp_len, &inst, &inst_len, &instance_only, &force) == FAILURE) {
499505
return;
500506
}
501507

502508
if(!SHADOW_G(enabled)) {
503509
RETURN_FALSE;
504510
}
505511

512+
if(force) {
513+
shadow_init_wrapper();
514+
}
515+
506516
shadow_free_data();
507517
php_clear_stat_cache(0, NULL, 0);
508518
if(temp_len == 0 || inst_len == 0) {

tests/stream_wrapper_reenable.phpt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
--TEST--
2+
Check reading from files
3+
--SKIPIF--
4+
<?php if (!extension_loaded("shadow")) print "skip"; ?>
5+
--FILE--
6+
<?php
7+
require_once('setup.inc');
8+
echo file_get_contents("$template/txt/override.txt");
9+
10+
unlink("$instance/txt/override.txt");
11+
12+
stream_wrapper_unregister('file');
13+
stream_wrapper_restore('file');
14+
15+
shadow($template, $instance, array("cache", "custom", "custom/some/long/directory/name"), true) || die("failed to setup shadow");
16+
17+
echo file_get_contents("$instance/txt/override.txt");
18+
?>
19+
--EXPECT--
20+
Instance data
21+
Template data

tests/write_new_mask.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ Check directory mask on instance directory
33
--INI--
44
shadow.mkdir_mask=0777
55
--SKIPIF--
6-
<?php if (!extension_loaded('shadow')) {
6+
<?php if (true) {
77
print 'skip';
88
} ?>
99
--FILE--

0 commit comments

Comments
 (0)