diff options
author | Brett Profitt <brett.profitt@gmail.com> | 2011-04-26 15:03:02 -0400 |
---|---|---|
committer | Brett Profitt <brett.profitt@gmail.com> | 2011-04-26 15:03:02 -0400 |
commit | c80ba5aa03264dd64c20ed8ae222e87f9371a44d (patch) | |
tree | 9355d87a9ab4570b9e54685ad9869cd4fedd392f /engine | |
parent | 581c2d35ae053aed07a607b8bb844603c48b7c2f (diff) | |
parent | 632cf13234d04a3f6b7acf67866a82e0bebde55c (diff) | |
download | elgg-c80ba5aa03264dd64c20ed8ae222e87f9371a44d.tar.gz elgg-c80ba5aa03264dd64c20ed8ae222e87f9371a44d.tar.bz2 |
Merge remote branch 'upstream/master'
Diffstat (limited to 'engine')
-rw-r--r-- | engine/classes/ElggPlugin.php | 39 | ||||
-rw-r--r-- | engine/classes/ElggPluginPackage.php | 19 | ||||
-rw-r--r-- | engine/lib/admin.php | 70 | ||||
-rw-r--r-- | engine/lib/annotations.php | 21 | ||||
-rw-r--r-- | engine/lib/elgglib.php | 42 | ||||
-rw-r--r-- | engine/lib/input.php | 2 | ||||
-rw-r--r-- | engine/lib/metastrings.php | 77 | ||||
-rw-r--r-- | engine/lib/plugins.php | 2 | ||||
-rw-r--r-- | engine/lib/statistics.php | 6 | ||||
-rw-r--r-- | engine/lib/views.php | 15 | ||||
-rw-r--r-- | engine/tests/api/metastrings.php | 2 | ||||
-rw-r--r-- | engine/tests/api/plugins.php | 10 | ||||
-rw-r--r-- | engine/tests/test_files/plugin_18/manifest.xml | 2 |
13 files changed, 220 insertions, 87 deletions
diff --git a/engine/classes/ElggPlugin.php b/engine/classes/ElggPlugin.php index 34e8e6732..20a8673de 100644 --- a/engine/classes/ElggPlugin.php +++ b/engine/classes/ElggPlugin.php @@ -30,7 +30,6 @@ class ElggPlugin extends ElggObject { $this->access_id = ACCESS_PUBLIC; } - /** * Loads the plugin by GUID or path. * @@ -91,7 +90,6 @@ class ElggPlugin extends ElggObject { } } - /** * Save the plugin object. Make sure required values exist. * @@ -138,7 +136,6 @@ class ElggPlugin extends ElggObject { return sanitise_filepath($this->path); } - /** * Sets the location of this plugin. * @@ -149,6 +146,23 @@ class ElggPlugin extends ElggObject { return $this->attributes['title'] = $id; } + /** + * Returns an array of available markdown files for this plugin + * + * @return array + */ + public function getAvailableTextFiles() { + $filenames = $this->package->getTextFilenames(); + + $files = array(); + foreach ($filenames as $filename) { + if ($this->canReadFile($filename)) { + $files[$filename] = "$this->path/$filename"; + } + } + + return $files; + } // Load Priority @@ -162,7 +176,6 @@ class ElggPlugin extends ElggObject { return $this->$name; } - /** * Sets the priority of the plugin * @@ -324,7 +337,6 @@ class ElggPlugin extends ElggObject { return $this->set($name, $value); } - /** * Removes a plugin setting name and value. * @@ -336,7 +348,6 @@ class ElggPlugin extends ElggObject { return remove_private_setting($this->guid, $name); } - /** * Removes all settings for this plugin. * @@ -496,7 +507,6 @@ class ElggPlugin extends ElggObject { return remove_private_setting($user->guid, $name); } - /** * Removes all User Settings for this plugin * @@ -517,7 +527,6 @@ class ElggPlugin extends ElggObject { return delete_data($q); } - /** * Removes this plugin's user settings for all users. * @@ -566,7 +575,6 @@ class ElggPlugin extends ElggObject { return true; } - /** * Is this plugin active? * @@ -591,7 +599,6 @@ class ElggPlugin extends ElggObject { return check_entity_relationship($this->guid, 'active_plugin', $site->guid); } - /** * Checks if this plugin can be activated on the current * Elgg installation. @@ -640,7 +647,7 @@ class ElggPlugin extends ElggObject { // if there are any on_enable functions, start the plugin now and run them // Note: this will not run re-run the init hooks! if ($return) { - if ($this->canIncludeFile('activate.php')) { + if ($this->canReadFile('activate.php')) { $flags = ELGG_PLUGIN_INCLUDE_START | ELGG_PLUGIN_REGISTER_CLASSES | ELGG_PLUGIN_REGISTER_LANGUAGES | ELGG_PLUGIN_REGISTER_VIEWS; @@ -660,7 +667,6 @@ class ElggPlugin extends ElggObject { return false; } - /** * Deactivates the plugin. * @@ -682,7 +688,7 @@ class ElggPlugin extends ElggObject { // run any deactivate code if ($return) { - if ($this->canIncludeFile('deactivate.php')) { + if ($this->canReadFile('deactivate.php')) { $return = $this->includeFile('deactivate.php'); } } @@ -694,7 +700,6 @@ class ElggPlugin extends ElggObject { } } - /** * Start the plugin. * @@ -750,7 +755,7 @@ class ElggPlugin extends ElggObject { $filepath = "$this->path/$filename"; - if (!$this->canIncludeFile($filename)) { + if (!$this->canReadFile($filename)) { $msg = elgg_echo('ElggPlugin:Exception:CannotIncludeFile', array($filename, $this->getID(), $this->guid, $this->path)); throw new PluginException($msg); @@ -765,8 +770,8 @@ class ElggPlugin extends ElggObject { * @param string $filename The name of the file * @return bool */ - protected function canIncludeFile($filename) { - return file_exists($this->path.'/'.$filename); + protected function canReadFile($filename) { + return is_readable($this->path . '/' . $filename); } /** diff --git a/engine/classes/ElggPluginPackage.php b/engine/classes/ElggPluginPackage.php index b2ec20549..4daab381e 100644 --- a/engine/classes/ElggPluginPackage.php +++ b/engine/classes/ElggPluginPackage.php @@ -28,6 +28,15 @@ class ElggPluginPackage { ); /** + * The optional files that can be read and served through the markdown page handler + * @var array + */ + private $textFiles = array( + 'README.txt', 'CHANGES.txt', + 'INSTALL.txt', 'COPYRIGHT.txt', 'LICENSE.txt' + ); + + /** * Valid types for provides. * * @var array @@ -286,6 +295,16 @@ class ElggPluginPackage { return false; } + /**************** + * Readme Files * + ***************/ + + /** + * Returns an array of present and readable text files + */ + public function getTextFilenames() { + return $this->textFiles; + } /*********************** * Dependencies system * diff --git a/engine/lib/admin.php b/engine/lib/admin.php index a9a0382cc..06418c44f 100644 --- a/engine/lib/admin.php +++ b/engine/lib/admin.php @@ -303,6 +303,7 @@ function admin_init() { elgg_register_page_handler('admin', 'admin_settings_page_handler'); elgg_register_page_handler('admin_plugin_screenshot', 'admin_plugin_screenshot_page_handler'); + elgg_register_page_handler('admin_plugin_text_file', 'admin_markdown_page_handler'); } /** @@ -446,7 +447,8 @@ function admin_settings_page_handler($page) { * @return true */ function admin_plugin_screenshot_page_handler($pages) { - admin_gatekeeper(); // only admins can use this - security feature + // only admins can use this for security + admin_gatekeeper(); $plugin_id = elgg_extract(0, $pages); // only thumbnail or full. @@ -485,6 +487,72 @@ function admin_plugin_screenshot_page_handler($pages) { } /** + * Formats and serves out markdown files from plugins. + * + * URLs in format like admin_plugin_text_file/<plugin_id>/filename.ext + * + * The only valid files are: + * * README.txt + * * CHANGES.txt + * * INSTALL.txt + * * COPYRIGHT.txt + * * LICENSE.txt + * + * @param type $page + */ +function admin_markdown_page_handler($pages) { + admin_gatekeeper(); + + elgg_set_context('admin'); + + elgg_unregister_css('elgg'); + $url = elgg_get_simplecache_url('js', 'admin'); + elgg_register_js('elgg.admin', $url); + elgg_load_js('elgg.admin'); + elgg_load_library('elgg:markdown'); + + $plugin_id = elgg_extract(0, $pages); + $plugin = elgg_get_plugin_from_id($plugin_id); + $filename = elgg_extract(1, $pages); + + $error = false; + + if (!$plugin) { + $error = elgg_echo('admin:plugins:markdown:unknown_plugin'); + } + + $text_files = $plugin->getAvailableTextFiles(); + + if (!array_key_exists($filename, $text_files)) { + $error = elgg_echo('admin:plugins:markdown:unknown_file'); + } + + $file = $text_files[$filename]; + $file_contents = file_get_contents($file); + + if (!$file_contents) { + $error = elgg_echo('admin:plugins:markdown:unknown_file'); + } + + if ($error) { + $title = $error; + $body = elgg_view_layout('admin', array('content' => $error, 'title' => $title)); + echo elgg_view_page($title, $body, 'admin'); + return true; + } + + $title = $plugin->manifest->getName() . ": $filename"; + $text = Markdown($file_contents); + + $body = elgg_view_layout('admin', array( + 'content' => $text, + 'title' => $title + )); + + echo elgg_view_page($title, $body, 'admin'); +} + +/** * Adds default admin widgets to the admin dashboard. * * @return void diff --git a/engine/lib/annotations.php b/engine/lib/annotations.php index 7a4e62921..80ffbe74e 100644 --- a/engine/lib/annotations.php +++ b/engine/lib/annotations.php @@ -388,13 +388,10 @@ function elgg_list_entities_from_annotations($options = array()) { /** * Get entities ordered by a mathematical calculation on annotation values * - * @todo I think at some point this could run through elgg_get_annotations() and pass a the callback - * as entity_row_to_elggstar - * * @param array $options An options array: * 'annotation_calculation' => The calculation to use. Must be a valid MySQL function. * Defaults to sum. Result selected as 'annotation_calculation'. - * 'order_by' => The order for the sorting. Defaults to 'calculation desc'. + * 'order_by' => The order for the sorting. Defaults to 'annotation_calculation desc'. * 'annotation_names' => The names of annotations on the entity. * 'annotation_values' => The values of annotations on the entity. * @@ -404,9 +401,10 @@ function elgg_list_entities_from_annotations($options = array()) { * @return mixed */ function elgg_get_entities_from_annotation_calculation($options) { + $db_prefix = elgg_get_config('dbprefix'); $defaults = array( - 'calculation' => 'sum', - 'order_by' => 'calculation desc' + 'calculation' => 'sum', + 'order_by' => 'annotation_calculation desc' ); $options = array_merge($defaults, $options); @@ -415,14 +413,13 @@ function elgg_get_entities_from_annotation_calculation($options) { // you must cast this as an int or it sorts wrong. $options['selects'][] = 'e.*'; - $options['selects'][] = "$function(cast(v.string as signed)) as calculation"; + $options['selects'][] = "$function(cast(a_msv.string as signed)) as annotation_calculation"; - // need our own join to get the values. -// $options['joins'][] = "JOIN {$db_prefix}metastrings msv ON a.value_id = msv.id"; -// $options['joins'][] = "JOIN {$db_prefix}entities ae ON a.entity_guid = ae.guid"; + // need our own join to get the values because the lower level functions don't + // add all the joins if it's a different callback. + $options['joins'][] = "JOIN {$db_prefix}metastrings a_msv ON n_table.value_id = a_msv.id"; - $options['wheres'][] = get_access_sql_suffix('n_table'); -// $options['wheres'][] = "e.guid = a.entity_guid"; + // don't need access control because it's taken care of by elgg_get_annotations. $options['group_by'] = 'n_table.entity_guid'; $options['callback'] = 'entity_row_to_elggstar'; diff --git a/engine/lib/elgglib.php b/engine/lib/elgglib.php index 6c94133df..e67f8b627 100644 --- a/engine/lib/elgglib.php +++ b/engine/lib/elgglib.php @@ -202,6 +202,7 @@ function elgg_unregister_js($name) { * * @param string $name Identifier of the JavaScript resource * + * @return void * @since 1.8.0 */ function elgg_load_js($name) { @@ -254,6 +255,7 @@ function elgg_unregister_css($name) { * * @param string $name Identifier of the CSS file * + * @return void * @since 1.8.0 */ function elgg_load_css($name) { @@ -354,8 +356,9 @@ function elgg_unregister_external_file($type, $name) { * Load an external resource for use on this page * * @param string $type Type of file: js or css - * @param string $name + * @param string $name The identifier for the file * + * @return void * @since 1.8.0 */ function elgg_load_external_file($type, $name) { @@ -1152,13 +1155,16 @@ function elgg_dump($value, $to_screen = TRUE, $level = 'NOTICE') { * * @see CODING.txt * - * @param str $msg Message to log / display. - * @param str $dep_version Human-readable *release* version: 1.7, 1.7.3 + * @param str $msg Message to log / display. + * @param str $dep_version Human-readable *release* version: 1.7, 1.7.3 + * @param int $backtrace_level How many levels back to display the backtrace. Useful if calling from + * functions that are called from other places (like elgg_view()). Set + * to -1 for a full backtrace. * * @return bool * @since 1.7.0 */ -function elgg_deprecated_notice($msg, $dep_version) { +function elgg_deprecated_notice($msg, $dep_version, $backtrace_level = 1) { // if it's a major release behind, visual and logged // if it's a 1 minor release behind, visual and logged // if it's for current minor release, logged. @@ -1192,9 +1198,26 @@ function elgg_deprecated_notice($msg, $dep_version) { // Get a file and line number for the log. Never show this in the UI. // Skip over the function that sent this notice and see who called the deprecated // function itself. + $msg .= " Called from "; + $stack = array(); $backtrace = debug_backtrace(); - $caller = $backtrace[1]; - $msg .= " (Called from {$caller['file']}:{$caller['line']})"; + // never show this call. + array_shift($backtrace); + $i = count($backtrace); + + foreach ($backtrace as $trace) { + $stack[] = "[#$i] {$trace['file']}:{$trace['line']}"; + $i--; + + if ($backtrace_level > 0) { + if ($backtrace_level <= 1) { + break; + } + $backtrace_level--; + } + } + + $msg .= implode("<br /> -> ", $stack); elgg_log($msg, 'WARNING'); @@ -1623,8 +1646,9 @@ function is_not_null($string) { * names by singular names. * * @param array $options The options array. $options['keys'] = 'values'; - * @param array $singulars A list of sinular words to pluralize by adding 's'. + * @param array $singulars A list of singular words to pluralize by adding 's'. * + * @access private * @return array * @since 1.7.0 */ @@ -1744,8 +1768,8 @@ function elgg_css_page_handler($page) { * * /<css||js>/name/of/view.<last_cache>.<css||js> * - * @param array $page The page array - * @param string $type The type: js or css + * @param array $page The page array + * @param string $type The type: js or css * * @return mixed */ diff --git a/engine/lib/input.php b/engine/lib/input.php index 25416b868..84752bc7d 100644 --- a/engine/lib/input.php +++ b/engine/lib/input.php @@ -237,7 +237,7 @@ function input_livesearch_page_handler($page) { exit; } - if (!$q = get_input('q')) { + if (!$q = get_input('term', get_input('q'))) { exit; } diff --git a/engine/lib/metastrings.php b/engine/lib/metastrings.php index 655617ac6..d444121d0 100644 --- a/engine/lib/metastrings.php +++ b/engine/lib/metastrings.php @@ -211,23 +211,29 @@ function delete_orphaned_metastrings() { * * @param array $options Array in format: * - * metastring_names => NULL|ARR metastring names + * metastring_names => NULL|ARR metastring names * - * metastring_values => NULL|ARR metastring values + * metastring_values => NULL|ARR metastring values * - * metastring_ids => NULL|ARR metastring ids + * metastring_ids => NULL|ARR metastring ids * - * metastring_case_sensitive => BOOL Overall Case sensitive + * metastring_case_sensitive => BOOL Overall Case sensitive * - * metastring_owner_guids => NULL|ARR guids for metadata owners + * metastring_owner_guids => NULL|ARR Guids for metadata owners * - * metastring_created_time_lower => INT Lower limit for created time. + * metastring_created_time_lower => INT Lower limit for created time. * - * metastring_created_time_upper => INT Upper limit for created time. + * metastring_created_time_upper => INT Upper limit for created time. * - * metastring_calculation => STR Perform the MySQL function on the metastring values returned. + * metastring_calculation => STR Perform the MySQL function on the metastring values + * returned. + * This differs from egef_annotation_calculation in that + * it returns only the calculation of all annotation values. + * You can sum, avg, count, etc. egef_annotation_calculation() + * returns ElggEntities ordered by a calculation on their + * annotation values. * - * metastring_type => STR metadata or annotation(s) + * metastring_type => STR metadata or annotation(s) * * @return mixed * @access private @@ -373,14 +379,35 @@ function elgg_get_metastring_based_objects($options) { } $joins = $options['joins']; - $joins[] = "JOIN {$db_prefix}entities e ON n_table.entity_guid = e.guid"; - $joins[] = "JOIN {$db_prefix}metastrings n on n_table.name_id = n.id"; - $joins[] = "JOIN {$db_prefix}metastrings v on n_table.value_id = v.id"; + // evaluate selects + if (!is_array($options['selects'])) { + $options['selects'] = array($options['selects']); + } - // remove identical join clauses - $joins = array_unique($joins); + $selects = $options['selects']; + + // allow count shortcut + if ($options['count']) { + $options['metastring_calculation'] = 'count'; + } + + // For performance reasons we don't want the joins required for metadata / annotations + // unless we're going through one of their callbacks. + // this means we expect the functions passing different callbacks to pass their required joins. + // If we're doing a calculation + $custom_callback = ($options['callback'] == 'row_to_elggmetadata' + || $options['callback'] == 'row_to_elggannotation'); + $is_calculation = $options['metastring_calculation'] ? true : false; + + if ($custom_callback || $is_calculation) { + $joins[] = "JOIN {$db_prefix}metastrings n on n_table.name_id = n.id"; + $joins[] = "JOIN {$db_prefix}metastrings v on n_table.value_id = v.id"; + + $selects[] = 'n.string as name'; + $selects[] = 'v.string as value'; + } foreach ($joins as $i => $join) { if ($join === FALSE) { @@ -400,28 +427,24 @@ function elgg_get_metastring_based_objects($options) { $joins = array_merge($joins, $metastring_clauses['joins']); } - // check for calculations - if ($options['count']) { - $options['metastring_calculation'] = 'count'; - } - if ($options['metastring_calculation'] === ELGG_ENTITIES_NO_VALUE) { + $selects = array_unique($selects); // evalutate selects - if ($options['selects']) { - $selects = ''; - foreach ($options['selects'] as $select) { - $selects .= ", $select"; + $select_str = ''; + if ($selects) { + foreach ($selects as $select) { + $select_str .= ", $select"; } - } else { - $selects = ''; } - $query = "SELECT DISTINCT n_table.*, n.string as name, - v.string as value{$selects} FROM {$db_prefix}$type n_table"; + $query = "SELECT DISTINCT n_table.*{$select_str} FROM {$db_prefix}$type n_table"; } else { $query = "SELECT {$options['metastring_calculation']}(v.string) as calculation FROM {$db_prefix}$type n_table"; } + // remove identical join clauses + $joins = array_unique($joins); + // add joins foreach ($joins as $j) { $query .= " $j "; diff --git a/engine/lib/plugins.php b/engine/lib/plugins.php index 3a144abc5..0947b7a8e 100644 --- a/engine/lib/plugins.php +++ b/engine/lib/plugins.php @@ -1088,6 +1088,8 @@ function plugin_init() { elgg_register_action('admin/plugins/deactivate_all', '', 'admin'); elgg_register_action('admin/plugins/set_priority', '', 'admin'); + + elgg_register_library('elgg:markdown', elgg_get_root_path() . 'vendors/markdown/markdown.php'); } elgg_register_event_handler('init', 'system', 'plugin_init'); diff --git a/engine/lib/statistics.php b/engine/lib/statistics.php index 4e822e8af..cd2b7a6a1 100644 --- a/engine/lib/statistics.php +++ b/engine/lib/statistics.php @@ -100,7 +100,11 @@ function get_online_users() { $objects = find_active_users(600, 10, $offset); if ($objects) { - return elgg_view_entity_list($objects, $count, $offset, 10, false); + return elgg_view_entity_list($objects, array( + 'count' => $count, + 'offset' => $offset, + 'limit' => 10 + )); } } diff --git a/engine/lib/views.php b/engine/lib/views.php index e2cf6b5c3..45b2c35f8 100644 --- a/engine/lib/views.php +++ b/engine/lib/views.php @@ -395,8 +395,10 @@ function elgg_view($view, $vars = array(), $bypass = false, $debug = false, $vie } // full_view is the new preferred key for full view on entities @see elgg_view_entity() - if (isset($vars['full'])) { - elgg_deprecated_notice("Use \$vars['full_view'] instead of \$vars['full']", 1.8); + // check if full_view is set because that means we've already rewritten it and this is + // coming from another view passing $vars directly. + if (isset($vars['full']) && !isset($vars['full_view'])) { + elgg_deprecated_notice("Use \$vars['full_view'] instead of \$vars['full']", 1.8, 2); $vars['full_view'] = $vars['full']; } if (isset($vars['full_view'])) { @@ -404,16 +406,17 @@ function elgg_view($view, $vars = array(), $bypass = false, $debug = false, $vie } // internalname => name (1.8) - if (isset($vars['internalname'])) { - elgg_deprecated_notice('You should pass $vars[\'name\'] now instead of $vars[\'internalname\']', 1.8); + if (isset($vars['internalname']) && !isset($vars['name'])) { + elgg_deprecated_notice('You should pass $vars[\'name\'] now instead of $vars[\'internalname\']', 1.8, 2); $vars['name'] = $vars['internalname']; + $test=false; } elseif (isset($vars['name'])) { $vars['internalname'] = $vars['name']; } // internalid => id (1.8) - if (isset($vars['internalid'])) { - elgg_deprecated_notice('You should pass $vars[\'id\'] now instead of $vars[\'internalid\']', 1.8); + if (isset($vars['internalid']) && !isset($vars['name'])) { + elgg_deprecated_notice('You should pass $vars[\'id\'] now instead of $vars[\'internalid\']', 1.8, 2); $vars['id'] = $vars['internalid']; } elseif (isset($vars['id'])) { $vars['internalid'] = $vars['id']; diff --git a/engine/tests/api/metastrings.php b/engine/tests/api/metastrings.php index e5cfe80e1..9b5d7ee4e 100644 --- a/engine/tests/api/metastrings.php +++ b/engine/tests/api/metastrings.php @@ -164,7 +164,7 @@ class ElggCoreMetastringsTest extends ElggCoreUnitTest { } $options = array(); - $this->assertFalse(elgg_is_valid_options_for_batch_operation($options), $type); + $this->assertFalse(elgg_is_valid_options_for_batch_operation($options, $type)); foreach ($required as $key) { $options = array(); diff --git a/engine/tests/api/plugins.php b/engine/tests/api/plugins.php index 853af45e9..00b0d4513 100644 --- a/engine/tests/api/plugins.php +++ b/engine/tests/api/plugins.php @@ -105,8 +105,6 @@ class ElggCorePluginsAPITest extends ElggCoreUnitTest { array('type' => 'plugin', 'name' => 'facebook_connect', 'version' => 1.0), ), - 'on_activate' => array('setup_function'), - 'on_deactivate' => array('teardown_function'), 'admin_interface' => 'simple', 'activate_on_install' => true ); @@ -279,14 +277,6 @@ class ElggCorePluginsAPITest extends ElggCoreUnitTest { $this->assertEqual($this->manifest17->getConflicts(), array()); } - public function testElggPluginManifestGetOnActivate() { - $this->assertEqual($this->manifest18->getOnActivate(), array('setup_function')); - } - - public function testElggPluginManifestGetOnDeactivate() { - $this->assertEqual($this->manifest18->getOnDeactivate(), array('teardown_function')); - } - public function testElggPluginManifestGetAdminInterface() { $this->assertEqual($this->manifest18->getAdminInterface(), 'simple'); } diff --git a/engine/tests/test_files/plugin_18/manifest.xml b/engine/tests/test_files/plugin_18/manifest.xml index c6cf4f807..23f0fa0bf 100644 --- a/engine/tests/test_files/plugin_18/manifest.xml +++ b/engine/tests/test_files/plugin_18/manifest.xml @@ -34,8 +34,6 @@ <category>ServiceAPI</category> - <on_activate>setup_function</on_activate> - <on_deactivate>teardown_function</on_deactivate> <admin_interface>simple</admin_interface> <activate_on_install>true</activate_on_install> |