diff --git a/.travis.yml b/.travis.yml index 0336bfca77..c9af814a53 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,32 +6,22 @@ php: # none of our dependencies allow 8.0 # - master -matrix: +os: linux + +jobs: fast_finish: true # allow_failures: # - php: master services: - memcached - - mysql #we use mariadb instead installed via addons below + - mysql # - postgres -#addons: -# mariadb: '10.0' - -sudo: required - before_script: - sudo apt-get update -qq - - sudo apt-get install -y libpcre3-dev + - sudo apt-get install -y libpcre3-dev apache2 libapache2-mod-fastcgi - case $(phpenv version-name) in - "5.6") - yes "" | pecl install memcache; - yes "" | pecl install apcu-4.0.11; - yes "" | pecl install igbinary; - echo "extension=memcached.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini; - phpenv config-rm xdebug.ini; - ;; "7"|"7.0"|"7.1"|"7.2") yes "" | pecl install apcu; echo "extension=memcached.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini; @@ -41,17 +31,19 @@ before_script: echo "extension=memcached.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini; ;; esac - - case $(phpenv version-name) in - "5.6") - composer require 'phpunit/phpunit:~5.7'; - ;; - "7"|"7.0") - composer require 'phpunit/phpunit:~6'; - ;; - *) - composer require --ignore-platform-reqs 'phpunit/phpunit:~7'; - ;; - esac + # enable apache with php-fpm see https://docs.travis-ci.com/user/languages/php/#apache--php + - sudo cp ~/.phpenv/versions/$(phpenv version-name)/etc/php-fpm.conf.default ~/.phpenv/versions/$(phpenv version-name)/etc/php-fpm.conf + - sudo a2enmod rewrite actions fastcgi alias + - echo "cgi.fix_pathinfo = 1" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini + - sudo sed -i -e "s,www-data,travis,g" /etc/apache2/envvars + - sudo chown -R travis:travis /var/lib/apache2/fastcgi + - ~/.phpenv/versions/$(phpenv version-name)/sbin/php-fpm + # configure apache virtual hosts + - sudo cp -f doc/travis-ci-apache.conf /etc/apache2/sites-available/000-default.conf + - sudo sed -e "s?%TRAVIS_BUILD_DIR%?$(pwd)?g" --in-place /etc/apache2/sites-available/000-default.conf + # remove .htaccess as it is read by Apache, but content is for mod_php + - rm -f .htaccess + - sudo service apache2 restart - php -m - php -i - php install-cli.php --ignore-platform-reqs @@ -64,7 +56,7 @@ script: # install egroupware using MariaDB as domain "default" # and add an admin user "demo" with password "guest" - php doc/rpm-build/post_install.php --domain default - --source_dir `pwd` --start_db '' --autostart_db '' --start_webserver '' --webserver_user '' + --source_dir `pwd` --start_db '' --autostart_db '' --start_webserver '' --autostart_webserver '' --webserver_user '' --admin_user demo --admin_passwd guest --admin_email noreply@example.com # disable PostgreSQL install as it fails in Travis with Fatal error: Call to unimplemented native function pg_set_client_encoding # install egroupware using PostgreSQL as domain "pgsql", need some specific handling we can not create users via sql @@ -79,8 +71,12 @@ script: # --source_dir `pwd` --start_db '' --autostart_db '' --start_webserver '' --webserver_user '' # Ubuntu has problems with #!/usr/bin/env php -dapc.enable=1, it stalls forever - vendor/bin/phpunit -c doc -dapc.enable_cli=1 + # output Apache error.log to diagnose PHP errors in requests send by unit-tests + - echo "travis_fold:start:SCRIPT folding starts" + - sudo cat /var/log/apache2/error.log # do not run syntax check for hhvm, as it always fails / get terminated after 10m - - test $(phpenv version-name) = 'hhvm' || ./doc/php_syntax_check.sh + - ./doc/php_syntax_check.sh + - echo "travis_fold:start:SCRIPT folding ends" cache: directories: diff --git a/admin/inc/class.admin_account.inc.php b/admin/inc/class.admin_account.inc.php index a576f3e43d..586bfef0cd 100644 --- a/admin/inc/class.admin_account.inc.php +++ b/admin/inc/class.admin_account.inc.php @@ -10,9 +10,9 @@ */ use EGroupware\Api; -use EGroupware\Api\Framework; use EGroupware\Api\Acl; use EGroupware\Api\Etemplate; +use EGroupware\Api\Framework; /** * UI for admin: edit/add account @@ -28,6 +28,13 @@ class admin_account 'delete' => true, ); + // Copying account uses addressbook fields, but we explicitly clear these + protected static $copy_clear_fields = array( + 'account_firstname','account_lastname','account_fullname', 'person_id', + 'account_id','account_lid', + 'account_lastlogin','accountlastloginfrom','account_lastpwd_change' + ); + /** * Hook to edit account data via "Account" tab in addressbook edit dialog * @@ -104,18 +111,24 @@ class admin_account } $readonlys['account_passwd'] = $readonlys['account_passwd2'] = true; } + // save old values to only trigger save, if one of the following values change (contact data get saved anyway) + $preserve = empty($content['id']) ? array() : + array('old_account' => array_intersect_key($account, array_flip(array( + 'account_lid', 'account_status', 'account_groups', 'anonymous', 'changepassword', + 'mustchangepassword', 'account_primary_group', 'homedirectory', 'loginshell', + 'account_expires', 'account_firstname', 'account_lastname', 'account_email'))), + 'deny_edit' => $deny_edit); + + if($content && $_GET['copy']) + { + $this->copy($content, $account, $preserve); + } return array( 'name' => 'admin.account', 'prepend' => true, 'label' => 'Account', 'data' => $account, - // save old values to only trigger save, if one of the following values change (contact data get saved anyway) - 'preserve' => empty($content['id']) ? array() : - array('old_account' => array_intersect_key($account, array_flip(array( - 'account_lid', 'account_status', 'account_groups', 'anonymous', 'changepassword', - 'mustchangepassword', 'account_primary_group', 'homedirectory', 'loginshell', - 'account_expires', 'account_firstname', 'account_lastname', 'account_email'))), - 'deny_edit' => $deny_edit), + 'preserve' => $preserve, 'readonlys' => $readonlys, 'pre_save_callback' => $deny_edit ? null : 'admin_account::addressbook_pre_save', ); @@ -243,6 +256,35 @@ class admin_account } } + public function copy(array &$content, array &$account, array &$preserve) + { + // We skipped the addressbook copy, call it now + $ab_ui = new addressbook_ui(); + $ab_ui->copy_contact($content, true); + + // copy_contact() reset the owner, fix it + $content['owner'] = '0'; + + // Explicitly, always clear these + static $clear_content = Array( + 'n_family','n_given','n_middle','n_suffix','n_fn','n_fileas', + 'account_id','contact_id','id','etag','carddav_name','uid' + ); + foreach($clear_content as $field) + { + $account[$field] =''; + $preserve[$field] = ''; + } + $account['link_to']['to_id'] = 0; + unset($preserve['old_account']); + + // Never copy these on an account + foreach(static::$copy_clear_fields as $field) + { + unset($account[$field]); + } + } + /** * Delete an account * diff --git a/admin/inc/class.admin_config.inc.php b/admin/inc/class.admin_config.inc.php index fbf00a2456..2b45fe4bee 100644 --- a/admin/inc/class.admin_config.inc.php +++ b/admin/inc/class.admin_config.inc.php @@ -139,7 +139,10 @@ class admin_config $_POST = array('newsettings' => &$_content['newsettings']); // Remove actual files (cleanup) of deselected urls from login_background_file - $this->remove_anon_images(array_diff((array)$c->config_data['login_background_file'], $_content['newsettings']['login_background_file'])); + if (!empty($c->config_data['login_background_file'])) + { + $this->remove_anon_images(array_diff((array)$c->config_data['login_background_file'], (array)$_content['newsettings']['login_background_file'])); + } /* Load hook file with functions to validate each config (one/none/all) */ $errors = Api\Hooks::single(array( diff --git a/admin/inc/class.admin_ui.inc.php b/admin/inc/class.admin_ui.inc.php index 7142af55f1..72e57db834 100644 --- a/admin/inc/class.admin_ui.inc.php +++ b/admin/inc/class.admin_ui.inc.php @@ -11,10 +11,10 @@ */ use EGroupware\Api; -use EGroupware\Api\Link; use EGroupware\Api\Egw; use EGroupware\Api\Etemplate; use EGroupware\Api\Etemplate\Widget\Tree; +use EGroupware\Api\Link; /** * UI for admin @@ -154,6 +154,13 @@ class admin_ui 'onExecute' => 'javaScript:app.admin.account', 'group' => $group, ), + 'copy' => array( + 'caption' => 'Copy', + 'url' => 'menuaction=addressbook.addressbook_ui.edit&makecp=1&contact_id=$id', + 'onExecute' => 'javaScript:app.admin.account', + 'allowOnMultiple' => false, + 'icon' => 'copy', + ), ); // generate urls for add/edit accounts via addressbook $edit = Link::get_registry('addressbook', 'edit'); diff --git a/admin/js/app.js b/admin/js/app.js index e68e7f8cbc..babd615654 100644 --- a/admin/js/app.js +++ b/admin/js/app.js @@ -760,11 +760,17 @@ var AdminApp = /** @class */ (function (_super) { AdminApp.prototype.account = function (_action, _senders) { var params = jQuery.extend({}, this.egw.link_get_registry('addressbook', 'edit')); var popup = this.egw.link_get_registry('addressbook', 'edit_popup'); - if (_action.id == 'add') { - params.owner = '0'; - } - else { - params.account_id = _senders[0].id.split('::').pop(); // get last :: separated part + switch (_action.id) { + case 'add': + params.owner = '0'; + break; + case 'copy': + params.owner = '0'; + params.copy = true; + // Fall through + default: + params.account_id = _senders[0].id.split('::').pop(); // get last :: separated part + break; } this.egw.open_link(this.egw.link('/index.php', params), 'admin', popup); }; diff --git a/admin/js/app.ts b/admin/js/app.ts index 8c6212fff3..b567d2dc90 100644 --- a/admin/js/app.ts +++ b/admin/js/app.ts @@ -888,14 +888,20 @@ class AdminApp extends EgwApp var params = jQuery.extend({}, this.egw.link_get_registry('addressbook', 'edit')); var popup = this.egw.link_get_registry('addressbook', 'edit_popup'); - if (_action.id == 'add') + switch(_action.id) { - params.owner = '0'; - } - else - { - params.account_id = _senders[0].id.split('::').pop(); // get last :: separated part + case 'add': + params.owner = '0'; + break; + case 'copy': + params.owner = '0'; + params.copy = true; + // Fall through + default: + params.account_id = _senders[0].id.split('::').pop(); // get last :: separated part + break; } + this.egw.open_link(this.egw.link('/index.php', params), 'admin', popup); } diff --git a/admin/templates/default/account.delete.xet b/admin/templates/default/account.delete.xet index 12cf9ba303..80288598c5 100644 --- a/admin/templates/default/account.delete.xet +++ b/admin/templates/default/account.delete.xet @@ -3,58 +3,85 @@