/** * Add a user image type * * @param string $code Code for image, also used for tpl tags * @param int $width Image maximum width * @param int $height Image maximum height * @param string $crop Crop ratio, or 'fit' to use width/height to calculate ratio * @return bool * @global CotDB $db * @global Cache $cache */ function cot_userimages_config_add($code, $width, $height, $crop = '', $force = false) { global $cache, $db, $db_users; if (empty($code)) { return FALSE; } $exists = $db->query("SHOW COLUMNS FROM {$db_users} LIKE 'user_" . $db->prep($code) . "'")->rowCount() > 0; if (!$exists) { $db->query("ALTER TABLE {$db_users} ADD `user_" . $db->prep($code) . "`\n\t\t\t\t\tvarchar(255) collate utf8_unicode_ci NOT NULL default ''"); } if (!$exists || $force) { $cfg = array(strval($width), strval($height)); if ($crop) { $cfg[] = $crop; } $options = array(array('name' => strtolower($code), 'type' => COT_CONFIG_TYPE_HIDDEN, 'default' => implode('x', $cfg), 'text' => $code)); $result = cot_config_add('userimages', $options); $cache && $cache->db->remove('cot_userimages_config', 'users'); return $result; } return FALSE; }
/** * Updates existing configuration map removing obsolete options, adding new * options and tweaking options which need to be updated. * * @param string $name Extension code * @param array $options Configuration options * @param bool $is_module TRUE for modules, FALSE for plugins * @param string $category Structure category code. Only for per-category config options * @param string $donor Extension name for extension-to-extension config implantations * @return int Number of entries affected */ function cot_config_update($name, $options, $is_module = false, $category = '', $donor = '') { $affected = 0; $old_options = cot_config_load($name, $is_module, $category, $donor); // Find and remove options which no longer exist $remove_opts = array(); foreach ($old_options as $old_opt) { $keep = false; foreach ($options as $opt) { if ($opt['name'] == $old_opt['name']) { $keep = true; break; } } if (!$keep && $old_opt['type'] != COT_CONFIG_TYPE_HIDDEN) { $remove_opts[] = $old_opt['name']; } } if (count($remove_opts) > 0) { $affected += cot_config_remove($name, $is_module, $remove_opts, $category, $donor); } // Find new options and options which have been modified $new_options = array(); $upd_options = array(); foreach ($options as $opt) { $existed = false; foreach ($old_options as $old_opt) { if ($opt['name'] == $old_opt['name']) { $changed = array_diff($opt, $old_opt); if (count($changed) > 0) { // Values for modified options are set to default // only if both type and default value have changed if ($opt['type'] != $old_opt['type'] && $opt['default'] != $old_opt['default']) { $opt['value'] = $opt['default']; } $upd_options[] = $opt; } $existed = true; break; } } if (!$existed) { $new_options[] = $opt; } } if (count($new_options) > 0) { $affected += cot_config_add($name, $new_options, $is_module, $category); } if (count($upd_options) > 0) { $affected += cot_config_modify($name, $upd_options, $is_module, $category); } return $affected; }
/** * Installs or updates a Cotonti extension: module or plugin. * Messages emitted during installation can be received through standard * Cotonti messages interface. * @param string $name Plugin code * @param bool $is_module TRUE for modules, FALSE for plugins * @param bool $update Perform update rather than new install * @param bool $force_update Forces extension update even if version has not changed * @return bool Operation status * @global Cache $cache */ function cot_extension_install($name, $is_module = false, $update = false, $force_update = false) { global $cfg, $L, $cache, $usr, $db_auth, $db_config, $db_users, $db_core, $cot_groups, $cot_ext_ignore_parts, $db, $db_x, $env; $path = $is_module ? $cfg['modules_dir'] . "/{$name}" : $cfg['plugins_dir'] . "/{$name}"; // Emit initial message if ($update) { cot_message(cot_rc('ext_updating', array('type' => $is_module ? $L['Module'] : $L['Plugin'], 'name' => $name))); } else { cot_message(cot_rc('ext_installing', array('type' => $is_module ? $L['Module'] : $L['Plugin'], 'name' => $name))); } // Check setup file and tags $setup_file = $path . "/{$name}.setup.php"; if (!file_exists($setup_file)) { cot_error(cot_rc('ext_setup_not_found', array('path' => $setup_file))); return false; } $old_ext_format = false; $info = cot_infoget($setup_file, 'COT_EXT'); if (!$info && cot_plugin_active('genoa')) { // Try load old format info $info = cot_infoget($setup_file, 'SED_EXTPLUGIN'); if ($info) { $old_ext_format = true; } } if ($info === false) { cot_error('ext_invalid_format'); return false; } // Check versions $res = $db->query("SELECT ct_version FROM {$db_core} WHERE ct_code = '{$name}'"); if ($res->rowCount() == 1) { $current_ver = $res->fetchColumn(); $res->closeCursor(); if ($update) { if (version_compare($current_ver, $info['Version']) == 0 && !$force_update) { // Nothing to update cot_message(cot_rc('ext_up2date', array('type' => $is_module ? $L['Module'] : $L['Plugin'], 'name' => $name))); return COT_EXT_NOTHING_TO_UPDATE; } } else { cot_clear_messages(); cot_error(cot_rc('ext_already_installed', array('name' => $name))); return false; } } if ($update) { // Safely drop existing bindings $bindings_cnt = cot_plugin_remove($name); cot_message(cot_rc('ext_bindings_uninstalled', array('cnt' => $bindings_cnt))); } // Install hook parts and bindings $hook_bindings = array(); $dp = opendir($path); while ($f = readdir($dp)) { if (preg_match("#^{$name}(\\.([\\w\\.]+))?.php\$#", $f, $mt) && !in_array($mt[2], $cot_ext_ignore_parts)) { $part_info = cot_infoget($path . "/{$f}", 'COT_EXT'); if (!$part_info && cot_plugin_active('genoa')) { // Try to load old format info $part_info = cot_infoget($path . "/{$f}", 'SED_EXTPLUGIN'); } if ($part_info) { if (empty($part_info['Hooks'])) { $hooks = $is_module ? array('module') : array('standalone'); } else { $hooks = explode(',', $part_info['Hooks']); $hooks = is_array($hooks) ? array_map('trim', $hooks) : array(); } if (empty($part_info['Order'])) { $order = COT_PLUGIN_DEFAULT_ORDER; } else { $order = array_map('trim', explode(',', $part_info['Order'])); if (count($order) == 1 || count($order) < count($hooks)) { $order = (int) $order[0]; } } $i = 0; foreach ($hooks as $hook) { $hook_bindings[] = array('part' => empty($mt[2]) ? 'main' : $mt[2], 'file' => $f, 'hook' => $hook, 'order' => isset($order[$i]) ? (int) $order[$i] : $order); ++$i; } } } } closedir($dp); $bindings_cnt = cot_plugin_add($hook_bindings, $name, $info['Name'], $is_module); cot_message(cot_rc('ext_bindings_installed', array('cnt' => $bindings_cnt))); // Install config $info_cfg = cot_infoget($setup_file, 'COT_EXT_CONFIG'); if (!$info_cfg && cot_plugin_active('genoa')) { // Try to load old format config $info_cfg = cot_infoget($setup_file, 'SED_EXTPLUGIN_CONFIG'); } $options = cot_config_parse($info_cfg, $is_module); if ($update) { // Get differential config if (cot_config_update($name, $options, $is_module) > 0) { cot_message('ext_config_updated'); } } elseif (count($options) > 0) { if (cot_config_add($name, $options, $is_module)) { cot_message('ext_config_installed'); } else { cot_error('ext_config_error'); return false; } } // Install structure config if present $info_cfg = cot_infoget($setup_file, 'COT_EXT_CONFIG_STRUCTURE'); if ($info_cfg) { $options = cot_config_parse($info_cfg, $is_module); if ($update) { if (cot_config_update($name, $options, $is_module, '__default') > 0) { // Update all nested categories $type = $is_module ? 'module' : 'plug'; $res = $db->query("SELECT DISTINCT config_subcat FROM {$db_config}\n\t\t\t\t\tWHERE config_owner = '{$type}' AND config_cat = '{$name}'\n\t\t\t\t\t\tAND config_subcat != '' AND config_subcat != '__default'"); $cat_list = $res->fetchAll(PDO::FETCH_COLUMN, 0); foreach ($cat_list as $cat) { cot_config_update($name, $options, $is_module, $cat); } cot_message('ext_config_struct_updated'); } } elseif (count($options) > 0) { if (cot_config_add($name, $options, $is_module, '__default')) { cot_message('ext_config_struct_installed'); } else { cot_error('ext_config_struct_error'); return false; } } } if ($update) { // Only update auth locks if ($is_module) { $auth_code = $name; $auth_option = 'a'; } else { $auth_code = 'plug'; $auth_option = $name; } $lock_guests = cot_auth_getvalue($info['Lock_guests']); $db->update($db_auth, array('auth_rights_lock' => $lock_guests), "\n\t\t\tauth_code = '{$auth_code}' AND auth_option = '{$auth_option}'\n\t\t\tAND (auth_groupid = " . COT_GROUP_GUESTS . ' OR auth_groupid = ' . COT_GROUP_INACTIVE . ')'); $lock_members = cot_auth_getvalue($info['Lock_members']); $ingore_groups = implode(',', array(COT_GROUP_GUESTS, COT_GROUP_INACTIVE, COT_GROUP_BANNED, COT_GROUP_SUPERADMINS)); $db->update($db_auth, array('auth_rights_lock' => $lock_members), "auth_code = '{$auth_code}' AND auth_option = '{$auth_option}' AND auth_groupid NOT IN ({$ingore_groups})"); cot_message('ext_auth_locks_updated'); } else { // Install auth $insert_rows = array(); foreach ($cot_groups as $v) { if (!$v['skiprights']) { if ($v['id'] == COT_GROUP_GUESTS || $v['id'] == COT_GROUP_INACTIVE) { $ins_auth = cot_auth_getvalue($info['Auth_guests']); $ins_lock = cot_auth_getvalue($info['Lock_guests']); if ($ins_auth > 128 || $ins_lock < 128) { $ins_auth = $ins_auth > 127 ? $ins_auth - 128 : $ins_auth; $ins_lock = 128; } } elseif ($v['id'] == COT_GROUP_BANNED) { $ins_auth = 0; $ins_lock = 255; } elseif ($v['id'] == COT_GROUP_SUPERADMINS) { $ins_auth = 255; $ins_lock = 255; } else { $ins_auth = cot_auth_getvalue($info['Auth_members']); $ins_lock = cot_auth_getvalue($info['Lock_members']); } if ($is_module) { $insert_rows[] = array('auth_groupid' => $v['id'], 'auth_code' => $name, 'auth_option' => 'a', 'auth_rights' => $ins_auth, 'auth_rights_lock' => $ins_lock, 'auth_setbyuserid' => $usr['id']); } else { $insert_rows[] = array('auth_groupid' => $v['id'], 'auth_code' => 'plug', 'auth_option' => $name, 'auth_rights' => $ins_auth, 'auth_rights_lock' => $ins_lock, 'auth_setbyuserid' => $usr['id']); } } } if ($db->insert($db_auth, $insert_rows)) { $db->update($db_users, array('user_auth' => ''), "user_auth != ''"); cot_message('ext_auth_installed'); } } if ($update) { // Find and apply patches if (file_exists("{$path}/setup")) { $new_ver = cot_apply_patches("{$path}/setup", $current_ver); } if (version_compare($info['Version'], $new_ver) > 0 || $new_ver === true) { $new_ver = $info['Version']; } } else { if (file_exists($path . "/setup/{$name}.install.sql")) { // Run SQL install script $sql_err = $db->runScript(file_get_contents("{$path}/setup/{$name}.install.sql")); if (empty($sql_err)) { cot_message(cot_rc('ext_executed_sql', array('ret' => 'OK'))); } else { cot_error(cot_rc('ext_executed_sql', array('ret' => $sql_err))); return false; } } $install_handler = $old_ext_format ? $setup_file : $path . "/setup/{$name}.install.php"; if ($old_ext_format) { global $action; $action = 'install'; } if (file_exists($install_handler)) { // Run PHP install handler $envtmp = $env; $env = array('ext' => $name, 'location' => $name, 'type' => $is_module ? 'module' : 'plug'); $ret = (include $install_handler); $env = $envtmp; if ($ret !== false) { $msg = $ret == 1 ? 'OK' : $ret; cot_message(cot_rc('ext_executed_php', array('ret' => $msg))); } else { cot_error(cot_rc('ext_executed_php', array('ret' => $msg ? $msg : $L['Error']))); return false; } } } // Register version information if ($update) { cot_extension_update($name, $new_ver, !$is_module); cot_message(cot_rc('ext_updated', array('type' => $is_module ? $L['Module'] : $L['Plugin'], 'name' => $name, 'ver' => $new_ver))); } else { cot_extension_add($name, $info['Name'], $info['Version'], !$is_module); } // Cleanup cot_auth_reorder(); $cache && $cache->clear(); return true; }