diff options
Diffstat (limited to 'phpBB')
47 files changed, 1756 insertions, 3674 deletions
diff --git a/phpBB/adm/index.php b/phpBB/adm/index.php index e7168b210b..91894e5aec 100644 --- a/phpBB/adm/index.php +++ b/phpBB/adm/index.php @@ -50,9 +50,9 @@ $file_uploads = (@ini_get('file_uploads') == '1' || strtolower(@ini_get('file_up $module_id = request_var('i', ''); $mode = request_var('mode', ''); -// Set custom template for admin area -$template->set_ext_dir_prefix('adm/'); -$template->set_custom_template($phpbb_admin_path . 'style', 'admin'); +// Set custom style for admin area +$style->set_ext_dir_prefix('adm/'); +$style->set_custom_style('admin', $phpbb_admin_path . 'style', ''); $template->assign_var('T_ASSETS_PATH', $phpbb_root_path . 'assets'); $template->assign_var('T_TEMPLATE_PATH', $phpbb_admin_path . 'style'); diff --git a/phpBB/adm/style/acp_styles.html b/phpBB/adm/style/acp_styles.html index 3532e8c7d9..b09cbafc95 100644 --- a/phpBB/adm/style/acp_styles.html +++ b/phpBB/adm/style/acp_styles.html @@ -2,399 +2,167 @@ <a id="maincontent"></a> -<!-- IF S_DELETE --> - - <a href="{U_BACK}" style="float: {S_CONTENT_FLOW_END};">« {L_BACK}</a> - - <h1>{L_TITLE}</h1> - - <p>{L_EXPLAIN}</p> - - <form id="acp_styles" method="post" action="{U_ACTION}"> - - <fieldset> - <legend>{L_TITLE}</legend> - <dl> - <dt><label>{L_NAME}:</label></dt> - <dd><strong>{NAME}</strong></dd> - </dl> - <dl> - <dt><label for="new_id">{L_REPLACE}:</label><br /><span>{L_REPLACE_EXPLAIN}</span></dt> - <dd><select id="new_id" name="new_id">{S_REPLACE_OPTIONS}</select></dd> - </dl> - <!-- IF S_DELETE_STYLE --> - <hr /> - <dl> - <dt><label for="new_template_id">{L_DELETE_TEMPLATE}:</label><br /><span>{L_REPLACE_TEMPLATE_EXPLAIN}</span></dt> - <dd><select id="new_template_id" name="new_template_id">{S_REPLACE_TEMPLATE_OPTIONS}</select></dd> - </dl> - <dl> - <dt><label for="new_theme_id">{L_DELETE_THEME}:</label><br /><span>{L_REPLACE_THEME_EXPLAIN}</span></dt> - <dd><select id="new_theme_id" name="new_theme_id">{S_REPLACE_THEME_OPTIONS}</select></dd> - </dl> +<!-- IF S_CONFIRM_ACTION --> +<form id="confirm" method="post" action="{S_CONFIRM_ACTION}"> + +<fieldset> + <h1>{MESSAGE_TITLE}</h1> + <p>{MESSAGE_TEXT}</p> + <!-- IF S_CONFIRM_DELETE --> + <label><input type="checkbox" class="checkbox" name="confirm_delete_files" /> {L_DELETE_FROM_FS}</label> <!-- ENDIF --> - <p class="quick"> - <input class="button1" type="submit" name="update" value="{L_DELETE}" /> - {S_FORM_TOKEN} - </p> - </fieldset> - </form> - -<!-- ELSEIF S_EDIT_TEMPLATE or S_EDIT_THEME --> + {S_HIDDEN_FIELDS} - <a href="{U_BACK}" style="float: {S_CONTENT_FLOW_END};">« {L_BACK}</a> + <div style="text-align: center;"> + <input type="submit" name="confirm" value="{L_YES}" class="button2" /> + <input type="submit" name="cancel" value="{L_NO}" class="button2" /> + </div> - <h1>{L_EDIT}</h1> +</fieldset> + +</form> +<!-- ELSE --> - <p>{L_EDIT_EXPLAIN}</p> +<!-- IF L_TITLE --><h1>{L_TITLE}</h1><!-- ENDIF --> - <p>{L_SELECTED}: <strong>{SELECTED_TEMPLATE}</strong></p> +<!-- IF L_EXPLAIN --><p>{L_EXPLAIN}</p><!-- ENDIF --> - <form id="acp_styles" method="post" action="{U_ACTION}"> +<form id="acp_styles" method="post" action="{U_ACTION}"> +{S_HIDDEN_FIELDS} +{S_FORM_TOKEN} - <!-- IF S_EDIT_TEMPLATE or (S_EDIT_THEME and not S_THEME_IN_DB) --> +<!-- IF S_STYLE_DETAILS --> + <input type="hidden" name="id" value="{STYLE_ID}" /> <fieldset> - <legend>{L_SELECT}</legend> <dl> - <dt><label for="template_file">{L_FILE}:</label></dt> - <dd><select id="template_file" name="template_file" onchange="if (this.options[this.selectedIndex].value != '') this.form.submit();">{S_TEMPLATES}</select> <input class="button2" type="submit" value="{L_SELECT}" /></dd> + <dt><label for="name">{L_STYLE_NAME}:</label></dt> + <dd><input type="text" id="name" name="style_name" value="{STYLE_NAME}" /></dd> </dl> - {S_FORM_TOKEN} - </fieldset> - <!-- ENDIF --> - </form> - - <!-- IF TEMPLATE_FILE or (S_EDIT_THEME and S_THEME_IN_DB) --> - <script type="text/javascript" defer="defer"> - // <![CDATA[ - - function change_editor_height(height) - { - height = Number(height); - - if (isNaN(height)) - { - return; - } - - editor = document.getElementById('template_data'); - editor.rows = Math.max(5, Math.min(height, 999)); - - append_text_rows('acp_styles', height); - append_text_rows('acp_template', height); - } - - function append_text_rows(form_name, value) - { - value = Number(value); - - if (isNaN(value)) - { - return; - } - - url = document.getElementById(form_name).action; - - // Make sure & is actually... & - url = url.replace(/&/g, '&'); - - var_start = url.indexOf('&text_rows='); - if (var_start == -1) - { - document.getElementById(form_name).action = url + "&text_rows=" + value; - } - else - { - url_start = url.substring(0, var_start + 1); - var_end = url.substring(var_start + 1).indexOf('&'); - if (var_end == -1) - { - document.getElementById(form_name).action = url_start + "text_rows=" + value; - } - else - { - document.getElementById(form_name).action = url_start + url.substring(var_end + var_start + 2) + "&text_rows=" + value; - } - } - } - - // ]]> - </script> - - <form id="acp_template" method="post" action="{U_ACTION}"> - - <fieldset> - <legend>{L_EDITOR}</legend> - <!-- IF S_EDIT_TEMPLATE or (S_EDIT_THEME and not S_THEME_IN_DB) --> - <dl> - <dt><label>{L_SELECTED_FILE}:</label></dt> - <dd>{TEMPLATE_FILE}</dd> - </dl> - <!-- ENDIF --> - <dl> - <dt><label for="text_rows">{L_EDITOR_HEIGHT}:</label></dt> - <dd><input id="text_rows" type="text" maxlength="3" value="{TEXT_ROWS}" /> <input class="button2" type="button" name="update" onclick="change_editor_height(this.form.text_rows.value);" value="{L_UPDATE}" /></dd> - </dl> - <textarea id="template_data" name="template_data" style="font-family:'Courier New', monospace;font-size:9pt;line-height:125%;width:100%;" cols="80" rows="{TEXT_ROWS}">{TEMPLATE_DATA}</textarea> - </fieldset> - - <fieldset class="submit-buttons"> - <legend>{L_SUBMIT}</legend> - {S_HIDDEN_FIELDS} - {S_FORM_TOKEN} - <input class="button1" id="save" type="submit" name="save" value="{L_SUBMIT}" /> - </fieldset> - </form> - <!-- ENDIF --> - -<!-- ELSEIF S_CACHE --> - - <a href="{U_BACK}" style="float: {S_CONTENT_FLOW_END};">« {L_BACK}</a> - - <h1>{L_TEMPLATE_CACHE}</h1> - - <p>{L_TEMPLATE_CACHE_EXPLAIN}</p> - - <form id="acp_styles" method="post" action="{U_ACTION}"> - <fieldset class="tabulated"> - <legend>{L_TEMPLATE_CACHE}</legend> - - <table cellspacing="1"> - <thead> - <tr> - <th>{L_CACHE_FILENAME}</th> - <th>{L_CACHE_FILESIZE}</th> - <th>{L_CACHE_CACHED}</th> - <th>{L_CACHE_MODIFIED}</th> - <th>{L_MARK}</th> - </tr> - </thead> - <tbody> - <!-- BEGIN file --> - <!-- IF file.S_ROW_COUNT is even --><tr class="row1"><!-- ELSE --><tr class="row2"><!-- ENDIF --> - <td><a href="{file.U_VIEWSOURCE}" onclick="popup(this.href, 750, 550, '_source'); return false;">{file.FILENAME_PATH}</a></td> - <td>{file.FILESIZE}</td> - <td>{file.CACHED}</td> - <td>{file.MODIFIED}</td> - <td><input type="checkbox" class="radio" name="delete[]" value="{file.FILENAME}" /></td> - </tr> - <!-- BEGINELSE --> - <tr class="row1"> - <td colspan="5">{L_TEMPLATE_CACHE_EMPTY}</td> - </tr> - <!-- END file --> - </tbody> - </table> - - <p class="quick"> - <span class="small"><a href="#" onclick="marklist('acp_styles', 'delete', true); return false;">{L_MARK_ALL}</a> :: <a href="#" onclick="marklist('acp_styles', 'delete', false); return false;">{L_UNMARK_ALL}</a></span><br /> - {S_FORM_TOKEN} - <input class="button1" type="submit" id="submit" name="submit" value="{L_DELETE_MARKED}" /> - </p> - </fieldset> - </form> - -<!-- ELSEIF S_EXPORT --> - - <a href="{U_BACK}" style="float: {S_CONTENT_FLOW_END};">« {L_BACK}</a> - - <h1>{L_TITLE}</h1> - - <p>{L_EXPLAIN}</p> - - <!-- IF S_ERROR_MSG --> - <div class="errorbox"> - <h3>{L_WARNING}</h3> - <p>{ERROR_MSG}</p> - </div> - <!-- ENDIF --> - - <form id="acp_styles" method="post" action="{U_ACTION}"> - - <fieldset> - <legend>{L_TITLE}</legend> <dl> - <dt><label>{L_NAME}:</label></dt> - <dd><strong>{NAME}</strong></dd> + <dt><label>{L_STYLE_PATH}</label></dt> + <dd><strong>{STYLE_PATH}</strong></dd> + </dl> + <dl> + <dt><label for="name">{L_COPYRIGHT}:</label></dt> + <dd><strong>{STYLE_COPYRIGHT}</strong></dd> </dl> - <!-- IF S_STYLE --> - <dl> - <dt><label for="inc_template">{L_INCLUDE_TEMPLATE}:</label></dt> - <dd><label><input type="radio" class="radio" id="inc_template" name="inc_template" value="1" checked="checked" /> {L_YES}</label> - <label><input type="radio" class="radio" name="inc_template" value="0" /> {L_NO}</label></dd> - </dl> - <dl> - <dt><label for="inc_theme">{L_INCLUDE_THEME}:</label></dt> - <dd><label><input type="radio" class="radio" id="inc_theme" name="inc_theme" value="1" checked="checked" /> {L_YES}</label> - <label><input type="radio" class="radio" name="inc_theme" value="0" /> {L_NO}</label></dd> - </dl> - <!-- ENDIF --> <dl> - <dt><label for="store">{L_DOWNLOAD_STORE}:</label><br /><span>{L_DOWNLOAD_STORE_EXPLAIN}</span></dt> - <dd><label><input type="radio" class="radio" id="store" name="store" value="1" checked="checked" /> {L_EXPORT_STORE}</label> - <label><input type="radio" class="radio" name="store" value="0" /> {L_EXPORT_DOWNLOAD}</label></dd> + <dt><label for="style_parent">{L_INHERITING_FROM}:</label></dt> + <dd><select id="style_parent" name="style_parent"> + <option value=""<!-- IF STYLE_PARENT == 0 --> selected="selected"<!-- ENDIF -->> - </option> + <!-- BEGIN parent_styles --> + <option value="{parent_styles.STYLE_ID}"<!-- IF parent_styles.STYLE_ID == STYLE_PARENT --> selected="selected"<!-- ENDIF -->>{parent_styles.SPACER}{parent_styles.STYLE_NAME}</option> + <!-- END parent_styles --> + </select></dd> </dl> <dl> - <dt><label for="format">{L_ARCHIVE_FORMAT}:</label></dt> - <dd>{FORMAT_BUTTONS}</dd> + <dt><label for="style_active">{L_STYLE_ACTIVE}:</label></dt> + <dd><label><input type="radio" class="radio" name="style_active" value="1"<!-- IF S_STYLE_ACTIVE --> id="style_active" checked="checked"<!-- ENDIF --> /> {L_YES}</label> + <label><input type="radio" class="radio" name="style_active" value="0"<!-- IF not S_STYLE_ACTIVE --> id="style_active" checked="checked"<!-- ENDIF --> /> {L_NO}</label></dd> </dl> + <!-- IF not S_STYLE_DEFAULT --> + <dl> + <dt><label for="style_default">{L_STYLE_DEFAULT}:</label></dt> + <dd><label><input type="radio" class="radio" name="style_default" value="1" /> {L_YES}</label> + <label><input type="radio" class="radio" id="style_default" name="style_default" value="0" checked="checked" /> {L_NO}</label></dd> + </dl> + <!-- ENDIF --> + </fieldset> - <p class="quick"> - {S_FORM_TOKEN} + <fieldset class="submit-buttons"> + <legend>{L_SUBMIT}</legend> <input class="button1" type="submit" name="update" value="{L_SUBMIT}" /> - </p> + <a href="{U_ACTION}" class="button2">{L_BACK}</a> + {S_FORM_TOKEN} </fieldset> +<!-- ENDIF --> - - </form> - -<!-- ELSEIF S_FRONTEND --> - - <h1>{L_TITLE}</h1> - - <p>{L_EXPLAIN}</p> - - <!-- IF S_STYLE --> <!-- DEFINE $COLSPAN = 5 --> <!-- ELSE --> <!-- DEFINE $COLSPAN = 4 --> <!-- ENDIF --> - +<!-- IF .styles_list --> <table cellspacing="1"> - <col class="row1" /><!-- IF S_STYLE --><col class="row1" /><!-- ENDIF --><col class="row2" /><col class="row2" /> <thead> <tr> - <th>{L_NAME}</th> - <!-- IF S_STYLE --><th>{L_STYLE_USED_BY}</th><!-- ENDIF --> - <th>{L_OPTIONS}</th> - <th>{L_ACTIONS}</th> + <th>{L_STYLE_NAME}</th> + <!-- IF not STYLES_LIST_HIDE_COUNT --><th width="10%" style="white-space: nowrap; text-align: center;">{L_STYLE_USED_BY}</th><!-- ENDIF --> + <th width="25%" style="white-space: nowrap; text-align: center;">{L_ACTIONS}</th> + {STYLES_LIST_EXTRA} + <th> </th> </tr> </thead> - <tbody> - <tr> - <td class="row3" colspan="{$COLSPAN}"><strong>{L_INSTALLED}</strong></td> - </tr> - <!-- BEGIN installed --> - <!-- IF installed.S_INACTIVE and not $INACTIVE_STYLES --> - <!-- DEFINE $INACTIVE_STYLES = 1 --> - <tr> - <td class="row3" colspan="{$COLSPAN}"><strong>{L_INACTIVE_STYLES}</strong></td> - </tr> - <!-- ENDIF --> - <tr> - <td><strong>{installed.NAME}</strong><!-- IF installed.S_DEFAULT_STYLE --> *<!-- ENDIF --></td> - <!-- IF S_STYLE --> - <td style="text-align: center;">{installed.STYLE_COUNT}</td> + <!-- BEGIN styles_list --> + <tbody id="styles-list-{styles_list.S_ROW_COUNT}"> + <tr<!-- IF styles_list.STYLE_ID and not styles_list.STYLE_ACTIVE --> class="row-inactive"<!-- ENDIF -->> + <!-- IF styles_list.LEVEL is odd --> + <!-- IF $ROW_CLASS == 'row1a' --><!-- DEFINE $ROW_CLASS = 'row1b' --><!-- ELSE --><!-- DEFINE $ROW_CLASS = 'row1a' --><!-- ENDIF --> + <!-- ELSE --> + <!-- IF $ROW_CLASS == 'row2a' --><!-- DEFINE $ROW_CLASS = 'row2b' --><!-- ELSE --><!-- DEFINE $ROW_CLASS = 'row2a' --><!-- ENDIF --> <!-- ENDIF --> - <td style="text-align: center;"> - {installed.S_OPTIONS} - </td> - <td style="text-align: center;"> - <!-- IF S_STYLE --> - <a href="{installed.U_STYLE_ACT_DEACT}" data-ajax="activate_deactivate">{installed.L_STYLE_ACT_DEACT}</a> | + <td class="{$ROW_CLASS}" style="padding-left: {styles_list.PADDING}px;"> + <!-- IF styles_list.STYLE_ID and styles_list.COMMENT == '' and styles_list.STYLE_ACTIVE --> + <div class="default-style" style="display: none; float: right;"> + <input class="radio" type="radio" name="default" value="{styles_list.STYLE_ID}"<!-- IF styles_list.DEFAULT --> checked="checked"<!-- ELSE --><!-- DEFINE $S_DEFAULT = 1 --><!-- ENDIF --> title="{L_STYLE_DEFAULT}" /> + </div> + <!-- ENDIF --> + <!-- IF styles_list.DEFAULT or styles_list.SHOW_COPYRIGHT --> + <strong>{styles_list.STYLE_NAME}</strong> + <!-- IF styles_list.SHOW_COPYRIGHT and styles_list.COMMENT == '' --><span><br />{styles_list.STYLE_COPYRIGHT}</span><!-- ENDIF --> + <!-- ELSE --> + <span>{styles_list.STYLE_NAME}</span> <!-- ENDIF --> - {installed.S_ACTIONS} - <!-- IF S_STYLE --> - | <a href="{installed.U_PREVIEW}">{L_PREVIEW}</a> + <!-- IF styles_list.COMMENT != '' --> + <span class="error"><br />{styles_list.COMMENT}</span> + <!-- ENDIF --> + <!-- IF not styles_list.STYLE_ID and styles_list.COMMENT == '' --> + <span class="style-path"><br />{L_STYLE_PATH} {styles_list.STYLE_PATH_FULL}</span> + <!-- ENDIF --> + </td> + <!-- IF not STYLES_LIST_HIDE_COUNT --> + <td class="{$ROW_CLASS}" style="text-align: center;">{styles_list.USERS}</td> + <!-- ENDIF --> + <td class="{$ROW_CLASS}" style="text-align: center;"> + <!-- BEGIN actions --> + <!-- IF styles_list.actions.S_ROW_COUNT > 0 --> | <!-- ENDIF --> + <!-- IF styles_list.actions.U_ACTION --> + <a href="{styles_list.actions.U_ACTION}"{styles_list.actions.U_ACTION_ATTR}>{styles_list.actions.L_ACTION}</a> + <!-- ENDIF --> + {styles_list.actions.HTML} + <!-- END actions --> + </td> + {styles_list.EXTRA} + <td class="{$ROW_CLASS}" width="20" style="text-align: center;"> + <!-- IF styles_list.STYLE_ID --> + <input class="checkbox" type="checkbox" name="ids[]" value="{styles_list.STYLE_ID}" /> + <!-- ELSE --> + <!-- IF styles_list.COMMENT != '' --> + + <!-- ELSE --> + <input class="checkbox" type="checkbox" name="dirs[]" value="{styles_list.STYLE_PATH}" /> + <!-- ENDIF --> <!-- ENDIF --> </td> </tr> - <!-- END installed --> - <tr> - <td class="row3" colspan="{$COLSPAN}"><strong>{L_UNINSTALLED}</strong></td> - </tr> - <!-- IF not .uninstalled --> - <tr> - <td class="row1" colspan="{$COLSPAN}" style="text-align: center;">{L_NO_UNINSTALLED}</td> - </tr> - <!-- ENDIF --> - <!-- BEGIN uninstalled --> - <tr> - <td<!-- IF S_STYLE --> colspan="2"<!-- ENDIF -->><strong>{uninstalled.NAME}</strong><br /><span>{L_COPYRIGHT}: {uninstalled.COPYRIGHT}</span></td> - <td style="text-align: center;" colspan="2"><a href="{uninstalled.U_INSTALL}">{L_INSTALL}</a></td> - </tr> - <!-- END uninstalled --> </tbody> + <!-- END styles_list --> </table> +<!-- ENDIF --> - <!-- IF S_STYLE --> - <form id="acp_styles" method="post" action="{U_ACTION}"> - - <fieldset class="quick"> - <legend>{L_CREATE}</legend> - {L_CREATE}: <input type="text" name="name" value="" /> {L_FROM} <select name="basis">{S_BASIS_OPTIONS}</select> <input class="button2" type="submit" name="add" value="{L_SUBMIT}" /> - </fieldset> - - </form> - <!-- ENDIF --> - -<!-- ELSEIF S_DETAILS --> - - <a href="{U_BACK}" style="float: {S_CONTENT_FLOW_END};">« {L_BACK}</a> - - <h1>{L_TITLE}</h1> - - <p>{L_EXPLAIN}</p> - - <!-- IF S_ERROR_MSG --> - <div class="errorbox"> - <h3>{L_WARNING}</h3> - <p>{ERROR_MSG}</p> - </div> - <!-- ENDIF --> - - <form id="acp_styles" method="post" action="{U_ACTION}"> - - <fieldset> - <legend>{L_TITLE}</legend> - <dl> - <dt><label for="name">{L_NAME}:</label></dt> - <dd><!-- IF S_INSTALL --><strong id="name">{NAME}</strong><!-- ELSE --><input type="text" id="name" name="name" value="{NAME}" /><!-- ENDIF --></dd> - </dl> - <dl> - <dt><label for="copyright">{L_COPYRIGHT}:</label></dt> - <dd><!-- IF S_INSTALL --><strong id="copyright">{COPYRIGHT}</strong><!-- ELSE --><input type="text" id="copyright" name="copyright" value="{COPYRIGHT}" /><!-- ENDIF --></dd> - </dl> - <!-- IF S_SUPERTEMPLATE --> - <dl> - <dt><label for="inheriting">{L_INHERITING_FROM}:</label></dt> - <dd><strong id="inheriting">{S_SUPERTEMPLATE}</strong></dd> - </dl> - <!-- ENDIF --> - <!-- IF S_STYLE and not S_BASIS --> - <dl> - <dt><label for="template_id">{L_STYLE_TEMPLATE}:</label></dt> - <dd><!-- IF S_INSTALL --><strong id="template_id">{TEMPLATE_NAME}</strong><!-- ELSE --><select id="template_id" name="template_id">{S_TEMPLATE_OPTIONS}</select><!-- ENDIF --></dd> - </dl> - <dl> - <dt><label for="theme_id">{L_STYLE_THEME}:</label></dt> - <dd><!-- IF S_INSTALL --><strong id="theme_id">{THEME_NAME}</strong><!-- ELSE --><select id="theme_id" name="theme_id">{S_THEME_OPTIONS}</select><!-- ENDIF --></dd> - </dl> - <!-- ENDIF --> - <!-- IF S_STYLE --> - </fieldset> - - <fieldset> - <legend>{L_OPTIONS}</legend> - <dl> - <dt><label for="style_active">{L_STYLE_ACTIVE}:</label></dt> - <dd><label><input type="radio" class="radio" name="style_active" value="1"<!-- IF S_STYLE_ACTIVE --> id="style_active" checked="checked"<!-- ENDIF --> /> {L_YES}</label> - <label><input type="radio" class="radio" name="style_active" value="0"<!-- IF not S_STYLE_ACTIVE --> id="style_active" checked="checked"<!-- ENDIF --> /> {L_NO}</label></dd> - </dl> - <!-- IF not S_STYLE_DEFAULT --> - <dl> - <dt><label for="style_default">{L_STYLE_DEFAULT}:</label></dt> - <dd><label><input type="radio" class="radio" name="style_default" value="1" /> {L_YES}</label> - <label><input type="radio" class="radio" id="style_default" name="style_default" value="0" checked="checked" /> {L_NO}</label></dd> - </dl> - <!-- ENDIF --> - <!-- ENDIF --> +<!-- IF .extra_actions --> + <fieldset class="quick"> + <!-- BEGIN extra_actions --> + <input type="submit" name="{extra_actions.ACTION_NAME}" class="button2" value="{extra_actions.L_ACTION}" /> + <!-- END extra_actions --> </fieldset> +<!-- ENDIF --> - <fieldset class="submit-buttons"> - <legend>{L_SUBMIT}</legend> - <input class="button1" type="submit" name="update" value="{L_SUBMIT}" /> - {S_FORM_TOKEN} +<!-- IF .extra_links --> + <fieldset class="quick"> + <!-- BEGIN extra_links --> + <a class="button2" href="{extra_links.U_ACTION}">{extra_links.L_ACTION}</a> + <!-- END extra_links --> </fieldset> +<!-- ENDIF --> - </form> +</form> <!-- ENDIF --> diff --git a/phpBB/adm/style/admin.css b/phpBB/adm/style/admin.css index d5dc957ac5..7afcc3d23b 100644 --- a/phpBB/adm/style/admin.css +++ b/phpBB/adm/style/admin.css @@ -630,12 +630,29 @@ td.name { .col1 { background-color: #DCEBFE; } .col2 { background-color: #F9F9F9; } +/* 4 row background colours for trees */ +.row1a { background-color: #F9F9F9; } +.row1b { background-color: #F6F6F6; } +.row2a { background-color: #E7EEF4; } +.row2b { background-color: #E3EBF2; } + .spacer { background-color: #DBDFE2; height: 1px; line-height: 1px; } +/* Deactivated row */ +.row-inactive { + color: #999; +} +.row-inactive a, .row-inactive strong { + color: #888; +} +.row-inactive a:hover { + color: #BC2A4D; +} + /* General form styles ----------------------------------------*/ fieldset { diff --git a/phpBB/common.php b/phpBB/common.php index 129f7e4881..3f039e49c0 100644 --- a/phpBB/common.php +++ b/phpBB/common.php @@ -123,9 +123,9 @@ set_config_count(null, null, null, $config); // load extensions $phpbb_extension_manager = new phpbb_extension_manager($db, EXT_TABLE, $phpbb_root_path, ".$phpEx", $cache->get_driver()); -$phpbb_template_locator = new phpbb_template_locator(); -$phpbb_template_path_provider = new phpbb_template_extension_path_provider($phpbb_extension_manager, new phpbb_template_path_provider()); -$template = new phpbb_template($phpbb_root_path, $phpEx, $config, $user, $phpbb_template_locator, $phpbb_template_path_provider); +// Initialize style +$style = new phpbb_style($phpbb_root_path, $phpEx, $config, $user, $phpbb_extension_manager); +$template = $style->template; $phpbb_subscriber_loader = new phpbb_event_extension_subscriber_loader($phpbb_dispatcher, $phpbb_extension_manager); $phpbb_subscriber_loader->load(); diff --git a/phpBB/develop/create_schema_files.php b/phpBB/develop/create_schema_files.php index 987c9152d4..4088657743 100644 --- a/phpBB/develop/create_schema_files.php +++ b/phpBB/develop/create_schema_files.php @@ -1655,43 +1655,14 @@ function get_schema_struct() 'style_name' => array('VCHAR_UNI:255', ''), 'style_copyright' => array('VCHAR_UNI', ''), 'style_active' => array('BOOL', 1), - 'template_id' => array('UINT', 0), - 'theme_id' => array('UINT', 0), + 'style_path' => array('VCHAR:100', ''), + 'bbcode_bitfield' => array('VCHAR:255', 'kNg='), + 'style_parent_id' => array('UINT:4', 0), + 'style_parent_tree' => array('TEXT', ''), ), 'PRIMARY_KEY' => 'style_id', 'KEYS' => array( 'style_name' => array('UNIQUE', 'style_name'), - 'template_id' => array('INDEX', 'template_id'), - 'theme_id' => array('INDEX', 'theme_id'), - ), - ); - - $schema_data['phpbb_styles_template'] = array( - 'COLUMNS' => array( - 'template_id' => array('UINT', NULL, 'auto_increment'), - 'template_name' => array('VCHAR_UNI:255', ''), - 'template_copyright' => array('VCHAR_UNI', ''), - 'template_path' => array('VCHAR:100', ''), - 'bbcode_bitfield' => array('VCHAR:255', 'kNg='), - 'template_inherits_id' => array('UINT:4', 0), - 'template_inherit_path' => array('VCHAR', ''), - ), - 'PRIMARY_KEY' => 'template_id', - 'KEYS' => array( - 'tmplte_nm' => array('UNIQUE', 'template_name'), - ), - ); - - $schema_data['phpbb_styles_theme'] = array( - 'COLUMNS' => array( - 'theme_id' => array('UINT', NULL, 'auto_increment'), - 'theme_name' => array('VCHAR_UNI:255', ''), - 'theme_copyright' => array('VCHAR_UNI', ''), - 'theme_path' => array('VCHAR:100', ''), - ), - 'PRIMARY_KEY' => 'theme_id', - 'KEYS' => array( - 'theme_name' => array('UNIQUE', 'theme_name'), ), ); diff --git a/phpBB/develop/mysql_upgrader.php b/phpBB/develop/mysql_upgrader.php index 69fcd690b7..88596e9461 100644 --- a/phpBB/develop/mysql_upgrader.php +++ b/phpBB/develop/mysql_upgrader.php @@ -1091,61 +1091,14 @@ function get_schema_struct() 'style_name' => array('VCHAR_UNI:255', ''), 'style_copyright' => array('VCHAR_UNI', ''), 'style_active' => array('BOOL', 1), - 'template_id' => array('UINT', 0), - 'theme_id' => array('UINT', 0), + 'style_path' => array('VCHAR:100', ''), + 'bbcode_bitfield' => array('VCHAR:255', 'kNg='), + 'style_parent_id' => array('UINT:4', 0), + 'style_parent_tree' => array('TEXT', ''), ), 'PRIMARY_KEY' => 'style_id', 'KEYS' => array( 'style_name' => array('UNIQUE', 'style_name'), - 'template_id' => array('INDEX', 'template_id'), - 'theme_id' => array('INDEX', 'theme_id'), - ), - ); - - $schema_data['phpbb_styles_template'] = array( - 'COLUMNS' => array( - 'template_id' => array('UINT', NULL, 'auto_increment'), - 'template_name' => array('VCHAR_UNI:255', ''), - 'template_copyright' => array('VCHAR_UNI', ''), - 'template_path' => array('VCHAR:100', ''), - 'bbcode_bitfield' => array('VCHAR:255', 'kNg='), - 'template_storedb' => array('BOOL', 0), - 'template_inherits_id' => array('UINT:4', 0), - 'template_inherit_path' => array('VCHAR', ''), - ), - 'PRIMARY_KEY' => 'template_id', - 'KEYS' => array( - 'tmplte_nm' => array('UNIQUE', 'template_name'), - ), - ); - - $schema_data['phpbb_styles_template_data'] = array( - 'COLUMNS' => array( - 'template_id' => array('UINT', 0), - 'template_filename' => array('VCHAR:100', ''), - 'template_included' => array('TEXT', ''), - 'template_mtime' => array('TIMESTAMP', 0), - 'template_data' => array('MTEXT_UNI', ''), - ), - 'KEYS' => array( - 'tid' => array('INDEX', 'template_id'), - 'tfn' => array('INDEX', 'template_filename'), - ), - ); - - $schema_data['phpbb_styles_theme'] = array( - 'COLUMNS' => array( - 'theme_id' => array('UINT', NULL, 'auto_increment'), - 'theme_name' => array('VCHAR_UNI:255', ''), - 'theme_copyright' => array('VCHAR_UNI', ''), - 'theme_path' => array('VCHAR:100', ''), - 'theme_storedb' => array('BOOL', 0), - 'theme_mtime' => array('TIMESTAMP', 0), - 'theme_data' => array('MTEXT_UNI', ''), - ), - 'PRIMARY_KEY' => 'theme_id', - 'KEYS' => array( - 'theme_name' => array('UNIQUE', 'theme_name'), ), ); diff --git a/phpBB/docs/coding-guidelines.html b/phpBB/docs/coding-guidelines.html index 5581c10786..f8aaf77441 100644 --- a/phpBB/docs/coding-guidelines.html +++ b/phpBB/docs/coding-guidelines.html @@ -71,7 +71,7 @@ <li><a href="#templating">Templating</a> <ol style="list-style-type: lower-roman;"> <li><a href="#templates">General Templating</a></li> - <li><a href="#inheritance">Template Inheritance</a></li> + <li><a href="#stylestree">Styles Tree</a></li> </ol></li> <li><a href="#charsets">Character Sets and Encodings</a></li> <li><a href="#translation">Translation (<abbr title="Internationalisation">i18n</abbr>/<abbr title="Localisation">L10n</abbr>) Guidelines</a> @@ -1623,24 +1623,25 @@ div </form> </pre></div><br /> - <a name="inheritance"></a><h3>4.ii. Template Inheritance</h3> - <p>When basing a new style on an existing one, it is not necessary to provide all the template files. By declaring the base style name in the <strong>inherit_from</strong> field in the template configuration file, the style can be set to inherit template files from the base style. The limitation on this is that the base style has to be installed and complete, meaning that it is not itself inheriting.</p> + <a name="stylestree"></a><h3>4.ii. Styles Tree</h3> + <p>When basing a new style on an existing one, it is not necessary to provide all the template files. By declaring the base style name in the <strong>parent</strong> field in the style configuration file, the style can be set to reuse template files from the parent style.</p> - <p>The effect of doing so is that the template engine will use the template files in the new style where they exist, but fall back to files in the base style otherwise. Declaring a style to inherit from another also causes it to use some of the configuration settings of the base style, notably database storage.</p> + <p>The effect of doing so is that the template engine will use the template files in the new style where they exist, but fall back to files in the parent style otherwise.</p> - <p>We strongly encourage the use of inheritance for styles based on the bundled styles, as it will ease the update procedure.</p> + <p>We strongly encourage the use of parent styles for styles based on the bundled styles, as it will ease the update procedure.</p> <div class="codebox"><pre> - # General Information about this template - name = inherits - copyright = © phpBB Group, 2007 - version = 3.0.3 +# General Information about this style +name = Custom Style +copyright = &copy; phpBB Group, 2007 +version = 3.1.0 - # Defining a different template bitfield - template_bitfield = lNg= +# Defining a different template bitfield +# template_bitfield = lNg= - # Are we inheriting? - inherit_from = prosilver +# Parent style +# Set value to empty or to this style's name if this style does not have a parent style +parent = prosilver </pre></div> </div> diff --git a/phpBB/includes/acp/acp_styles.php b/phpBB/includes/acp/acp_styles.php index 26939080bc..acd010b77e 100644 --- a/phpBB/includes/acp/acp_styles.php +++ b/phpBB/includes/acp/acp_styles.php @@ -21,2602 +21,1291 @@ if (!defined('IN_PHPBB')) class acp_styles { var $u_action; - - var $style_cfg; - var $template_cfg; - var $theme_cfg; + var $u_base_action; + var $s_hidden_fields; + var $mode; + var $styles_path; + var $styles_path_absolute = 'styles'; function main($id, $mode) { - global $db, $user, $auth, $template, $cache, $request; - global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; + global $user, $phpbb_admin_path, $phpbb_root_path, $phpEx, $template, $request; - // Hardcoded template bitfield to add for new templates - $bitfield = new bitfield(); - $bitfield->set(0); - $bitfield->set(1); - $bitfield->set(2); - $bitfield->set(3); - $bitfield->set(4); - $bitfield->set(8); - $bitfield->set(9); - $bitfield->set(11); - $bitfield->set(12); - $this->template_bitfield = $bitfield->get_base64(); - unset($bitfield); + $this->styles_path = $phpbb_root_path . $this->styles_path_absolute . '/'; + + $this->u_base_action = append_sid("{$phpbb_admin_path}index.$phpEx", "i={$id}"); + $this->s_hidden_fields = array( + 'mode' => $mode, + ); $user->add_lang('acp/styles'); $this->tpl_name = 'acp_styles'; $this->page_title = 'ACP_CAT_STYLES'; + $this->mode = $mode; - $action = request_var('action', ''); - $action = (isset($_POST['add'])) ? 'add' : $action; - $style_id = request_var('id', 0); - - // Fill the configuration variables - $this->style_cfg = $this->template_cfg = $this->theme_cfg = ' -# -# phpBB {MODE} configuration file -# -# @package phpBB3 -# @copyright (c) 2005 phpBB Group -# @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 -# -# -# At the left is the name, please do not change this -# At the right the value is entered -# For on/off options the valid values are on, off, 1, 0, true and false -# -# Values get trimmed, if you want to add a space in front or at the end of -# the value, then enclose the value with single or double quotes. -# Single and double quotes do not need to be escaped. -# -# - -# General Information about this {MODE} -name = {NAME} -copyright = {COPYRIGHT} -version = {VERSION} -'; - - $this->template_cfg .= ' -# Some configuration options - -# Template inheritance -# See http://blog.phpbb.com/2008/07/31/templating-just-got-easier/ -# Set value to empty or this template name to ignore template inheritance. -inherit_from = {INHERIT_FROM} -'; - - // Execute overall actions - switch ($action) + $action = $request->variable('action', ''); + $post_actions = array('install', 'activate', 'deactivate', 'delete'); + foreach ($post_actions as $key) { - case 'delete': - if ($style_id) - { - $this->remove($mode, $style_id); - return; - } - break; - - case 'export': - if ($style_id) - { - $this->export($mode, $style_id); - return; - } - break; + if (isset($_POST[$key])) + { + $action = $key; + } + } + if ($action != '') + { + $this->s_hidden_fields['action'] = $action; + } + $template->assign_vars(array( + 'U_ACTION' => $this->u_base_action, + 'S_HIDDEN_FIELDS' => build_hidden_fields($this->s_hidden_fields) + ) + ); + + // Execute actions + switch ($action) + { case 'install': - $this->install($mode); + $this->action_install(); return; - break; - - case 'add': - $this->add($mode); + case 'delete': + $this->action_delete(); + return; + case 'activate': + $this->action_activate(); + return; + case 'deactivate': + $this->action_deactivate(); return; - break; - case 'details': - if ($style_id) - { - $this->details($mode, $style_id); - return; - } - break; - - case 'edit': - if ($style_id) - { - switch ($mode) - { - case 'template': - return $this->edit_template($style_id); - case 'theme': - return $this->edit_theme($style_id); - } - } - break; - - case 'cache': - if ($style_id) - { - switch ($mode) - { - case 'template': - return $this->template_cache($style_id); - } - } - break; + $this->action_details(); + return; + default: + $this->frontend(); } - - switch ($mode) + } + + /** + * Main page + */ + function frontend() + { + // Check mode + switch ($this->mode) { case 'style': - - switch ($action) - { - case 'activate': - case 'deactivate': - - if ($style_id == $config['default_style']) - { - trigger_error($user->lang['DEACTIVATE_DEFAULT'] . adm_back_link($this->u_action), E_USER_WARNING); - } - - if (($action == 'deactivate' && confirm_box(true)) || $action == 'activate') - { - $sql = 'UPDATE ' . STYLES_TABLE . ' - SET style_active = ' . (($action == 'activate') ? 1 : 0) . ' - WHERE style_id = ' . $style_id; - $db->sql_query($sql); - - // Set style to default for any member using deactivated style - if ($action == 'deactivate') - { - $sql = 'UPDATE ' . USERS_TABLE . ' - SET user_style = ' . $config['default_style'] . " - WHERE user_style = $style_id"; - $db->sql_query($sql); - - $sql = 'UPDATE ' . FORUMS_TABLE . ' - SET forum_style = 0 - WHERE forum_style = ' . $style_id; - $db->sql_query($sql); - } - - if ($request->is_ajax()) - { - $json_response = new phpbb_json_response; - $json_response->send(array( - 'text' => $user->lang['STYLE_' . (($action == 'activate') ? 'DE' : '') . 'ACTIVATE'], - 'MESSAGE_TITLE' => $user->lang['INFORMATION'], - 'MESSAGE_TEXT' => $user->lang['STYLE_' . strtoupper($action) . 'D'], - 'REFRESH_DATA' => array( - 'time' => 3 - ) - )); - } - } - else if ($action == 'deactivate') - { - $s_hidden_fields = array( - 'i' => $id, - 'mode' => $mode, - 'action' => $action, - 'style_id' => $style_id, - ); - confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields($s_hidden_fields)); - } - break; - } - - $this->frontend('style', array('details'), array('export', 'delete')); - break; - - case 'template': - - switch ($action) - { - // Clear cache - case 'refresh': - - $sql = 'SELECT * - FROM ' . STYLES_TEMPLATE_TABLE . " - WHERE template_id = $style_id"; - $result = $db->sql_query($sql); - $template_row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - if (!$template_row) - { - trigger_error($user->lang['NO_TEMPLATE'] . adm_back_link($this->u_action), E_USER_WARNING); - } - - if (confirm_box(true)) - { - $this->clear_template_cache($template_row); - - trigger_error($user->lang['TEMPLATE_CACHE_CLEARED'] . adm_back_link($this->u_action)); - } - else - { - confirm_box(false, $user->lang['CONFIRM_TEMPLATE_CLEAR_CACHE'], build_hidden_fields(array( - 'i' => $id, - 'mode' => $mode, - 'action' => $action, - 'id' => $style_id - ))); - } - - break; - } - - $this->frontend('template', array('edit', 'cache', 'details'), array('refresh', 'export', 'delete')); - break; - - case 'theme': - $this->frontend('theme', array('edit', 'details'), array('export', 'delete')); - break; + $this->welcome_message('ACP_STYLES', 'ACP_STYLES_EXPLAIN'); + $this->show_installed(); + return; + case 'install': + $this->welcome_message('INSTALL_STYLES', 'INSTALL_STYLES_EXPLAIN'); + $this->show_available(); + return; + case 'cache': + $this->action_cache(); + return; } + global $user; + trigger_error($user->lang['NO_MODE'] . adm_back_link($this->u_action), E_USER_WARNING); } - + /** - * Build Frontend with supplied options + * Purge cache */ - function frontend($mode, $options, $actions) + function action_cache() { - global $user, $template, $db, $config, $phpbb_root_path, $phpEx; - - $sql_from = ''; - $sql_sort = 'LOWER(' . $mode . '_name)'; - $style_count = array(); + global $cache, $auth, $user; + + $cache->purge(); - switch ($mode) - { - case 'style': - $sql_from = STYLES_TABLE; - $sql_sort = 'style_active DESC, ' . $sql_sort; + // Clear permissions + $auth->acl_clear_prefetch(); + cache_moderators(); - $sql = 'SELECT user_style, COUNT(user_style) AS style_count - FROM ' . USERS_TABLE . ' - GROUP BY user_style'; - $result = $db->sql_query($sql); - - while ($row = $db->sql_fetchrow($result)) + add_log('admin', 'LOG_PURGE_CACHE'); + + trigger_error($user->lang['PURGED_CACHE'] . adm_back_link($this->u_base_action), E_USER_NOTICE); + } + + /** + * Install style(s) + */ + function action_install() + { + global $user; + + // Get list of styles to install + $dirs = $this->request_vars('dir', '', true); + + // Get list of styles that can be installed + $styles = $this->find_available(false); + + // Install each style + $messages = array(); + $installed_names = array(); + $installed_dirs = array(); + $last_installed = false; + foreach ($dirs as $dir) + { + $found = false; + foreach ($styles as &$style) + { + // Check if: + // 1. Directory matches directory we are looking for + // 2. Style is not installed yet + // 3. Style with same name or directory hasn't been installed already within this function + if ($style['style_path'] == $dir && empty($style['_installed']) && !in_array($style['style_path'], $installed_dirs) && !in_array($style['style_name'], $installed_names)) { - $style_count[$row['user_style']] = $row['style_count']; + // Install style + $style['style_active'] = 1; + $style['style_id'] = $this->install_style($style); + $style['_installed'] = true; + $found = true; + $last_installed = $style['style_id']; + $installed_names[] = $style['style_name']; + $installed_dirs[] = $style['style_path']; + $messages[] = sprintf($user->lang['STYLE_INSTALLED'], htmlspecialchars($style['style_name'])); } - $db->sql_freeresult($result); - - break; - - case 'template': - $sql_from = STYLES_TEMPLATE_TABLE; - break; - - case 'theme': - $sql_from = STYLES_THEME_TABLE; - break; - - default: - trigger_error($user->lang['NO_MODE'] . adm_back_link($this->u_action), E_USER_WARNING); - } - - $l_prefix = strtoupper($mode); - - $this->page_title = 'ACP_' . $l_prefix . 'S'; - - $template->assign_vars(array( - 'S_FRONTEND' => true, - 'S_STYLE' => ($mode == 'style') ? true : false, - - 'L_TITLE' => $user->lang[$this->page_title], - 'L_EXPLAIN' => $user->lang[$this->page_title . '_EXPLAIN'], - 'L_NAME' => $user->lang[$l_prefix . '_NAME'], - 'L_INSTALLED' => $user->lang['INSTALLED_' . $l_prefix], - 'L_UNINSTALLED' => $user->lang['UNINSTALLED_' . $l_prefix], - 'L_NO_UNINSTALLED' => $user->lang['NO_UNINSTALLED_' . $l_prefix], - 'L_CREATE' => $user->lang['CREATE_' . $l_prefix], - - 'U_ACTION' => $this->u_action, - ) - ); - - $sql = "SELECT * - FROM $sql_from - ORDER BY $sql_sort ASC"; - $result = $db->sql_query($sql); - - $installed = array(); - - $basis_options = '<option class="sep" value="">' . $user->lang['OPTIONAL_BASIS'] . '</option>'; - while ($row = $db->sql_fetchrow($result)) - { - $installed[] = $row[$mode . '_name']; - $basis_options .= '<option value="' . $row[$mode . '_id'] . '">' . $row[$mode . '_name'] . '</option>'; - - $stylevis = ($mode == 'style' && !$row['style_active']) ? 'activate' : 'deactivate'; - - $s_options = array(); - foreach ($options as $option) - { - $s_options[] = '<a href="' . $this->u_action . "&action=$option&id=" . $row[$mode . '_id'] . '">' . $user->lang[strtoupper($option)] . '</a>'; } - - $s_actions = array(); - foreach ($actions as $option) + if (!$found) { - $data_ajax = ($option == 'refresh') ? ' data-ajax="true"' : ''; - $s_actions[] = '<a href="' . $this->u_action . "&action=$option&id=" . $row[$mode . '_id'] . '"' . $data_ajax . '>' . $user->lang[strtoupper($option)] . '</a>'; + $messages[] = sprintf($user->lang['STYLE_NOT_INSTALLED'], htmlspecialchars($dir)); } - - $template->assign_block_vars('installed', array( - 'S_DEFAULT_STYLE' => ($mode == 'style' && $row['style_id'] == $config['default_style']) ? true : false, - 'U_EDIT' => $this->u_action . '&action=' . (($mode == 'style') ? 'details' : 'edit') . '&id=' . $row[$mode . '_id'], - 'U_STYLE_ACT_DEACT' => $this->u_action . '&action=' . $stylevis . '&id=' . $row[$mode . '_id'], - 'L_STYLE_ACT_DEACT' => $user->lang['STYLE_' . strtoupper($stylevis)], - 'S_OPTIONS' => implode(' | ', $s_options), - 'S_ACTIONS' => implode(' | ', $s_actions), - 'U_PREVIEW' => ($mode == 'style') ? append_sid("{$phpbb_root_path}index.$phpEx", "$mode=" . $row[$mode . '_id']) : '', - - 'NAME' => $row[$mode . '_name'], - 'STYLE_COUNT' => ($mode == 'style' && isset($style_count[$row['style_id']])) ? $style_count[$row['style_id']] : 0, - - 'S_INACTIVE' => ($mode == 'style' && !$row['style_active']) ? true : false, - ) - ); } - $db->sql_freeresult($result); - - // Grab uninstalled items - $new_ary = $cfg = array(); - - $dp = @opendir("{$phpbb_root_path}styles"); - - if ($dp) + + // Show message + if (!count($messages)) { - while (($file = readdir($dp)) !== false) - { - if ($file[0] == '.' || !is_dir($phpbb_root_path . 'styles/' . $file)) - { - continue; - } - - $subpath = ($mode != 'style') ? "$mode/" : ''; - if (file_exists("{$phpbb_root_path}styles/$file/$subpath$mode.cfg")) - { - if ($cfg = file("{$phpbb_root_path}styles/$file/$subpath$mode.cfg")) - { - $items = parse_cfg_file('', $cfg); - $name = (isset($items['name'])) ? trim($items['name']) : false; - - if ($name && !in_array($name, $installed)) - { - $new_ary[] = array( - 'path' => $file, - 'name' => $name, - 'copyright' => $items['copyright'], - ); - } - } - } - } - closedir($dp); + trigger_error($user->lang['NO_MATCHING_STYLES_FOUND'] . adm_back_link($this->u_action), E_USER_WARNING); } - - unset($installed); - - if (sizeof($new_ary)) + $message = implode('<br />', $messages); + if (count($messages) == 1 && $last_installed !== false) { - foreach ($new_ary as $cfg) - { - $template->assign_block_vars('uninstalled', array( - 'NAME' => $cfg['name'], - 'COPYRIGHT' => $cfg['copyright'], - 'U_INSTALL' => $this->u_action . '&action=install&path=' . urlencode($cfg['path'])) - ); - } + $message .= '<br /><br />' . sprintf($user->lang['STYLE_INSTALLED_EDIT_DETAILS'], $this->u_base_action . '&mode=style&action=details&id=' . $last_installed); } - unset($new_ary); - - $template->assign_vars(array( - 'S_BASIS_OPTIONS' => $basis_options) - ); - + $message .= '<br /><br />' . sprintf($user->lang['STYLE_INSTALLED_RETURN_STYLES'], $this->u_base_action . '&mode=style'); + $message .= '<br /><br />' . sprintf($user->lang['STYLE_INSTALLED_RETURN_UNINSTALLED'], $this->u_base_action . '&mode=install'); + trigger_error($message, E_USER_NOTICE); } - + /** - * Provides a template editor which allows saving changes to template files on the filesystem or in the database. - * - * @param int $template_id specifies which template set is being edited + * Confirm styles deletion */ - function edit_template($template_id) + function action_delete() { - global $phpbb_root_path, $phpEx, $config, $db, $cache, $user, $template, $safe_mode; - - if (defined('PHPBB_DISABLE_ACP_EDITOR')) - { - trigger_error($user->lang['EDITOR_DISABLED'] . adm_back_link($this->u_action)); + global $user, $config, $template, $request; + + // Get list of styles to delete + $ids = $this->request_vars('id', 0, true); + + // Check if confirmation box was submitted + if (confirm_box(true)) + { + // Delete + $this->action_delete_confirmed($ids, $request->variable('confirm_delete_files', false)); + return; } + + // Confirm box + $s_hidden = build_hidden_fields(array( + 'action' => 'delete', + 'ids' => $ids + )); + $template->assign_var('S_CONFIRM_DELETE', true); + confirm_box(false, $user->lang['CONFIRM_DELETE_STYLES'], $s_hidden, 'acp_styles.html'); + + // Canceled - show styles list + $this->frontend(); + } - $this->page_title = 'EDIT_TEMPLATE'; - - $filelist = $filelist_cats = array(); - - $template_data = utf8_normalize_nfc(request_var('template_data', '', true)); - $template_data = htmlspecialchars_decode($template_data); - $template_file = utf8_normalize_nfc(request_var('template_file', '', true)); - $text_rows = max(5, min(999, request_var('text_rows', 20))); - $save_changes = (isset($_POST['save'])) ? true : false; - - // make sure template_file path doesn't go upwards - $template_file = preg_replace('#\.{2,}#', '.', $template_file); - - // Retrieve some information about the template - $sql = 'SELECT template_path, template_name - FROM ' . STYLES_TEMPLATE_TABLE . " - WHERE template_id = $template_id"; - $result = $db->sql_query($sql); - $template_info = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - if (!$template_info) - { - trigger_error($user->lang['NO_TEMPLATE'] . adm_back_link($this->u_action), E_USER_WARNING); - } + /** + * Delete styles(s) + * + * @param array $ids List of style IDs + * @param bool $delete_files If true, script will attempt to remove files for selected styles + */ + function action_delete_confirmed($ids, $delete_files) + { + global $db, $user, $cache; - // Get the filesystem location of the current file - $template_path = "{$phpbb_root_path}styles/{$template_info['template_path']}/template"; - $file = "$template_path/$template_file"; + $default = $config['default_style']; + $deleted = array(); + $messages = array(); - if ($template_file) + // Check styles list + foreach ($ids as $id) { - $l_not_writable = sprintf($user->lang['TEMPLATE_FILE_NOT_WRITABLE'], htmlspecialchars($template_file)) . adm_back_link($this->u_action); - - if ($safe_mode) + if (!$id) { - trigger_error($l_not_writable, E_USER_WARNING); + trigger_error($user->lang['INVALID_STYLE_ID'] . adm_back_link($this->u_action), E_USER_WARNING); } - - if (file_exists($file) && is_file($file) && is_readable($file)) - { - if (!phpbb_is_writable($file)) - { - trigger_error($l_not_writable, E_USER_WARNING); - } - } - else + if ($id == $default) { - trigger_error($user->lang['NO_TEMPLATE'] . adm_back_link($this->u_action), E_USER_WARNING); + trigger_error($user->lang['DELETE_DEFAULT'] . adm_back_link($this->u_action), E_USER_WARNING); } + $deleted[$id] = false; } - if ($save_changes && !check_form_key('acp_styles')) - { - trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); - } - else if (!$save_changes) - { - add_form_key('acp_styles'); - } + // Order by reversed style_id, so parent styles would be removed after child styles + // This way parent and child styles can be removed in same function call + $sql = 'SELECT * + FROM ' . STYLES_TABLE . ' + WHERE style_id IN (' . implode(', ', $ids) . ') + ORDER BY style_id DESC'; + $result = $db->sql_query($sql); - // save changes to the template if the user submitted any - if ($save_changes && $template_file) + $rows = $db->sql_fetchrowset($result); + $db->sql_freeresult($result); + + // Delete each style + $deleted = array(); + foreach ($rows as $style) { - // Try to write the file - if (!($fp = @fopen($file, 'wb'))) + $result = $this->delete_style($style, $delete_files); + + if (is_string($result)) { - // File exists and is writeable, but still not able to be written to - trigger_error($l_not_writable, E_USER_WARNING); + $messages[] = $result; + continue; } - fwrite($fp, $template_data); - fclose($fp); + $messages[] = sprintf($user->lang['STYLE_DELETED'], $style['style_name']); + $deleted[] = $style['style_name']; - // destroy the cached version of the template (filename without extension) - $this->clear_template_cache($template_info, array(substr($template_file, 0, -5))); - - $cache->destroy('sql', STYLES_TABLE); - - add_log('admin', 'LOG_TEMPLATE_EDIT', $template_info['template_name'], $template_file); - trigger_error($user->lang['TEMPLATE_FILE_UPDATED'] . adm_back_link($this->u_action . "&action=edit&id=$template_id&text_rows=$text_rows&template_file=$template_file")); - } - - // Generate a category array containing template filenames - - $filelist = filelist($template_path, '', 'html'); - $filelist[''] = array_diff($filelist[''], array('bbcode.html')); - - if ($template_file) - { - $template_data = file_get_contents($file); - - if (!$template_data) + // Attempt to delete files + if ($delete_files) { - trigger_error($user->lang['NO_TEMPLATE'] . adm_back_link($this->u_action), E_USER_WARNING); + $messages[] = sprintf($user->lang[$this->delete_style_files($style['style_path']) ? 'DELETE_STYLE_FILES_SUCCESS' : 'DELETE_STYLE_FILES_FAILED'], $style['style_name']); } } - if (empty($filelist[''])) + if (empty($messages)) { - trigger_error($user->lang['NO_TEMPLATE'] . adm_back_link($this->u_action), E_USER_WARNING); + // Nothing to delete? + trigger_error($user->lang['NO_MATCHING_STYLES_FOUND'] . adm_back_link($this->u_action), E_USER_WARNING); } - // Now create the categories - $filelist_cats[''] = array(); - foreach ($filelist as $pathfile => $file_ary) + // Log action + if (count($deleted)) { - // Use the directory name as category name - if (!empty($pathfile)) - { - $filelist_cats[$pathfile] = array(); - foreach ($file_ary as $file) - { - $filelist_cats[$pathfile][$pathfile . $file] = $file; - } - } - // or if it's in the main category use the word before the first underscore to group files - else - { - $cats = array(); - foreach ($file_ary as $file) - { - $cats[] = substr($file, 0, strpos($file, '_')); - $filelist_cats[substr($file, 0, strpos($file, '_'))][$file] = $file; - } - - $cats = array_values(array_unique($cats)); - - // we don't need any single element categories so put them into the misc '' category - for ($i = 0, $n = sizeof($cats); $i < $n; $i++) - { - if (sizeof($filelist_cats[$cats[$i]]) == 1 && $cats[$i] !== '') - { - $filelist_cats[''][key($filelist_cats[$cats[$i]])] = current($filelist_cats[$cats[$i]]); - unset($filelist_cats[$cats[$i]]); - } - } - unset($cats); - } + add_log('admin', 'LOG_STYLE_DELETE', implode(', ', $deleted)); } - unset($filelist); - - // Generate list of categorised template files - $tpl_options = ''; - ksort($filelist_cats); - foreach ($filelist_cats as $category => $tpl_ary) - { - ksort($tpl_ary); - - if (!empty($category)) - { - $tpl_options .= '<option class="sep" value="">' . $category . '</option>'; - } - foreach ($tpl_ary as $filename => $file) - { - $selected = ($template_file == $filename) ? ' selected="selected"' : ''; - $tpl_options .= '<option value="' . $filename . '"' . $selected . '>' . $file . '</option>'; - } - } + // Clear cache + $cache->purge(); - $template->assign_vars(array( - 'S_EDIT_TEMPLATE' => true, - 'S_HIDDEN_FIELDS' => build_hidden_fields(array('template_file' => $template_file)), - 'S_TEMPLATES' => $tpl_options, - - 'U_ACTION' => $this->u_action . "&action=edit&id=$template_id&text_rows=$text_rows", - 'U_BACK' => $this->u_action, - - 'L_EDIT' => $user->lang['EDIT_TEMPLATE'], - 'L_EDIT_EXPLAIN' => $user->lang['EDIT_TEMPLATE_EXPLAIN'], - 'L_EDITOR' => $user->lang['TEMPLATE_EDITOR'], - 'L_EDITOR_HEIGHT' => $user->lang['TEMPLATE_EDITOR_HEIGHT'], - 'L_FILE' => $user->lang['TEMPLATE_FILE'], - 'L_SELECT' => $user->lang['SELECT_TEMPLATE'], - 'L_SELECTED' => $user->lang['SELECTED_TEMPLATE'], - 'L_SELECTED_FILE' => $user->lang['SELECTED_TEMPLATE_FILE'], - - 'SELECTED_TEMPLATE' => $template_info['template_name'], - 'TEMPLATE_FILE' => $template_file, - 'TEMPLATE_DATA' => utf8_htmlspecialchars($template_data), - 'TEXT_ROWS' => $text_rows) - ); + // Show message + trigger_error(implode('<br />', $messages) . adm_back_link($this->u_action), E_USER_NOTICE); } /** - * Allows the admin to view cached versions of template files and clear single template cache files - * - * @param int $template_id specifies which template's cache is shown + * Activate styles */ - function template_cache($template_id) + function action_activate() { - global $phpbb_root_path, $phpEx, $config, $db, $cache, $user, $template; - - $source = str_replace('/', '.', request_var('source', '')); - $file_ary = array_diff(request_var('delete', array('')), array('')); - $submit = isset($_POST['submit']) ? true : false; - - $sql = 'SELECT * - FROM ' . STYLES_TEMPLATE_TABLE . " - WHERE template_id = $template_id"; - $result = $db->sql_query($sql); - $template_row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); + global $user, $config, $cache, $db; + + // Get list of styles to activate + $ids = $this->request_vars('id', 0, true); + + // Activate styles + $sql = 'UPDATE ' . STYLES_TABLE . ' + SET style_active = 1 + WHERE style_id IN (' . implode(', ', $ids) . ')'; + $db->sql_query($sql); - if (!$template_row) - { - trigger_error($user->lang['NO_TEMPLATE'] . adm_back_link($this->u_action), E_USER_WARNING); - } + // Purge cache + $cache->destroy('sql', STYLES_TABLE); + + // Show styles list + $this->frontend(); + } - // User wants to delete one or more files ... - if ($submit && $file_ary) - { - $this->clear_template_cache($template_row, $file_ary); - trigger_error($user->lang['TEMPLATE_CACHE_CLEARED'] . adm_back_link($this->u_action . "&action=cache&id=$template_id")); - } + /** + * Deactivate styles + */ + function action_deactivate() + { + global $user, $config, $cache, $db; - $cache_prefix = 'tpl_' . str_replace('_', '-', $template_row['template_path']); + // Get list of styles to deactivate + $ids = $this->request_vars('id', 0, true); - // Someone wants to see the cached source ... so we'll highlight it, - // add line numbers and indent it appropriately. This could be nasty - // on larger source files ... - if ($source && file_exists("{$phpbb_root_path}cache/{$cache_prefix}_$source.html.$phpEx")) + // Check for default style + foreach ($ids as $id) { - adm_page_header($user->lang['TEMPLATE_CACHE']); - - $template->set_filenames(array( - 'body' => 'viewsource.html') - ); - - $template->assign_vars(array( - 'FILENAME' => str_replace('.', '/', $source) . '.html') - ); - - $code = str_replace(array("\r\n", "\r"), array("\n", "\n"), file_get_contents("{$phpbb_root_path}cache/{$cache_prefix}_$source.html.$phpEx")); - - $conf = array('highlight.bg', 'highlight.comment', 'highlight.default', 'highlight.html', 'highlight.keyword', 'highlight.string'); - foreach ($conf as $ini_var) - { - @ini_set($ini_var, str_replace('highlight.', 'syntax', $ini_var)); - } - - $marker = 'MARKER' . time(); - $code = highlight_string(str_replace("\n", $marker, $code), true); - $code = str_replace($marker, "\n", $code); - $str_from = array('<span style="color: ', '<font color="syntax', '</font>', '<code>', '</code>','[', ']', '.', ':'); - $str_to = array('<span class="', '<span class="syntax', '</span>', '', '', '[', ']', '.', ':'); - - $code = str_replace($str_from, $str_to, $code); - $code = preg_replace('#^(<span class="[a-z_]+">)\n?(.*?)\n?(</span>)$#ism', '$1$2$3', $code); - $code = substr($code, strlen('<span class="syntaxhtml">')); - $code = substr($code, 0, -1 * strlen('</ span>')); - $code = explode("\n", $code); - - foreach ($code as $key => $line) + if ($id == $config['default_style']) { - $template->assign_block_vars('source', array( - 'LINENUM' => $key + 1, - 'LINE' => preg_replace('#([^ ;]) ([^ &])#', '$1 $2', $line)) - ); - unset($code[$key]); + trigger_error($user->lang['DEACTIVATE_DEFAULT'] . adm_back_link($this->u_action), E_USER_WARNING); } - - adm_page_footer(); } - // Get a list of cached template files and then retrieve additional information about them - $file_ary = $this->template_cache_filelist($template_row['template_path']); - - foreach ($file_ary as $file) - { - $file = str_replace('/', '.', $file); - - // perform some dirty guessing to get the path right. - // We assume that three dots in a row were '../' - $tpl_file = str_replace('.', '/', $file); - $tpl_file = str_replace('///', '../', $tpl_file); - - $filename = "{$cache_prefix}_$file.html.$phpEx"; - - if (!file_exists("{$phpbb_root_path}cache/$filename")) - { - continue; - } - - $file_tpl = "{$phpbb_root_path}styles/{$template_row['template_path']}/template/$tpl_file.html"; - $inherited = false; - - if (isset($template_row['template_inherits_id']) && $template_row['template_inherits_id'] && !file_exists($file_tpl)) - { - $file_tpl = "{$phpbb_root_path}styles/{$template_row['template_inherit_path']}/template/$tpl_file.html"; - $inherited = true; - } - - $template->assign_block_vars('file', array( - 'U_VIEWSOURCE' => $this->u_action . "&action=cache&id=$template_id&source=$file", + // Reset default style for users who use selected styles + $sql = 'UPDATE ' . USERS_TABLE . ' + SET user_style = 0 + WHERE user_style IN (' . implode(', ', $ids) . ')'; + $db->sql_query($sql); - 'CACHED' => $user->format_date(filemtime("{$phpbb_root_path}cache/$filename")), - 'FILENAME' => $file, - 'FILENAME_PATH' => $file_tpl, - 'FILESIZE' => get_formatted_filesize(filesize("{$phpbb_root_path}cache/$filename")), - 'MODIFIED' => $user->format_date(filemtime($file_tpl)), - )); - } + // Deactivate styles + $sql = 'UPDATE ' . STYLES_TABLE . ' + SET style_active = 0 + WHERE style_id IN (' . implode(', ', $ids) . ')'; + $db->sql_query($sql); - $template->assign_vars(array( - 'S_CACHE' => true, - 'S_TEMPLATE' => true, + // Purge cache + $cache->destroy('sql', STYLES_TABLE); - 'U_ACTION' => $this->u_action . "&action=cache&id=$template_id", - 'U_BACK' => $this->u_action) - ); + // Show styles list + $this->frontend(); } - + /** - * Provides a css editor and a basic easier to use stylesheet editing tool for less experienced (or lazy) users - * - * @param int $theme_id specifies which theme is being edited + * Show style details */ - function edit_theme($theme_id) + function action_details() { - global $phpbb_root_path, $phpEx, $config, $db, $cache, $user, $template, $safe_mode; - - $this->page_title = 'EDIT_THEME'; - - $filelist = $filelist_cats = array(); - - $theme_data = utf8_normalize_nfc(request_var('template_data', '', true)); - $theme_data = htmlspecialchars_decode($theme_data); - $theme_file = utf8_normalize_nfc(request_var('template_file', '', true)); - $text_rows = max(5, min(999, request_var('text_rows', 20))); - $save_changes = (isset($_POST['save'])) ? true : false; - - // make sure theme_file path doesn't go upwards - $theme_file = str_replace('..', '.', $theme_file); - - // Retrieve some information about the theme - $sql = 'SELECT theme_path, theme_name - FROM ' . STYLES_THEME_TABLE . " - WHERE theme_id = $theme_id"; - $result = $db->sql_query($sql); - - if (!($theme_info = $db->sql_fetchrow($result))) + global $user, $config, $db, $request, $template, $cache; + + $id = $request->variable('id', 0); + if (!$id) { - trigger_error($user->lang['NO_THEME'] . adm_back_link($this->u_action), E_USER_WARNING); - } - $db->sql_freeresult($result); - - // Get the filesystem location of the current file - $theme_path = "{$phpbb_root_path}styles/{$theme_info['theme_path']}/theme"; - $file = "$theme_path/$theme_file"; - - if ($theme_file) - { - $l_not_writable = sprintf($user->lang['THEME_FILE_NOT_WRITABLE'], htmlspecialchars($theme_file)) . adm_back_link($this->u_action); - - if ($safe_mode) - { - trigger_error($l_not_writable, E_USER_WARNING); - } - - if (file_exists($file) && is_file($file) && is_readable($file)) - { - if (!phpbb_is_writable($file)) - { - trigger_error($l_not_writable, E_USER_WARNING); - } - } - else - { - trigger_error($user->lang['NO_THEME'] . adm_back_link($this->u_action), E_USER_WARNING); - } + trigger_error($user->lang['NO_MATCHING_STYLES_FOUND'] . adm_back_link($this->u_action), E_USER_WARNING); } - - // save changes to the theme if the user submitted any - if ($save_changes && $theme_file) + + // Get all styles + $styles = $this->get_styles(); + usort($styles, 'acp_styles::sort_styles'); + + // Find current style + $style = false; + foreach ($styles as $row) { - $message = $user->lang['THEME_UPDATED']; - - if (!($fp = @fopen($file, 'wb'))) + if ($row['style_id'] == $id) { - trigger_error($l_not_writable, E_USER_WARNING); + $style = $row; + break; } - fwrite($fp, $theme_data); - fclose($fp); - - $cache->destroy('sql', STYLES_THEME_TABLE); - add_log('admin', 'LOG_THEME_EDIT_FILE', $theme_info['theme_name'], $theme_file); - - trigger_error($message . adm_back_link($this->u_action . "&action=edit&id=$theme_id&template_file=$theme_file&text_rows=$text_rows")); } - // Generate a category array containing theme filenames - $filelist = filelist($theme_path, '', 'css'); - - if ($theme_file) + if ($style === false) { - $theme_data = file_get_contents($file); - - if (!$theme_data) - { - trigger_error($user->lang['NO_THEME'] . adm_back_link($this->u_action), E_USER_WARNING); - } + trigger_error($user->lang['NO_MATCHING_STYLES_FOUND'] . adm_back_link($this->u_action), E_USER_WARNING); } - - // Now create the categories - $filelist_cats[''] = array(); - foreach ($filelist as $pathfile => $file_ary) + + // Find all available parent styles + $list = $this->find_possible_parents($styles, $id); + + // Change data + if ($request->variable('update', false)) { - // Use the directory name as category name - if (!empty($pathfile)) + $update = array( + 'style_name' => trim($request->variable('style_name', $style['style_name'])), + 'style_parent_id' => $request->variable('style_parent', (int) $style['style_parent_id']), + 'style_active' => $request->variable('style_active', (int) $style['style_active']), + ); + $update_action = $this->u_action . '&action=details&id=' . $id; + + // Check style name + if ($update['style_name'] != $style['style_name']) { - $filelist_cats[$pathfile] = array(); - foreach ($file_ary as $file) + if (!strlen($update['style_name'])) + { + trigger_error($user->lang['STYLE_ERR_STYLE_NAME'] . adm_back_link($update_action), E_USER_WARNING); + } + foreach ($styles as $row) { - $filelist_cats[$pathfile][$pathfile . $file] = $file; + if ($row['style_name'] == $update['style_name']) + { + trigger_error($user->lang['STYLE_ERR_NAME_EXIST'] . adm_back_link($update_action), E_USER_WARNING); + } } } - // or if it's in the main category use the word before the first underscore to group files else { - $cats = array(); - foreach ($file_ary as $file) - { - $cats[] = substr($file, 0, strpos($file, '_')); - $filelist_cats[substr($file, 0, strpos($file, '_'))][$file] = $file; - } - - $cats = array_values(array_unique($cats)); - - // we don't need any single element categories so put them into the misc '' category - for ($i = 0, $n = sizeof($cats); $i < $n; $i++) + unset($update['style_name']); + } + + // Check parent style id + if ($update['style_parent_id'] != $style['style_parent_id']) + { + if ($update['style_parent_id'] != 0) { - if (sizeof($filelist_cats[$cats[$i]]) == 1 && $cats[$i] !== '') + $found = false; + foreach ($list as $row) + { + if ($row['style_id'] == $update['style_parent_id']) + { + $found = true; + $update['style_parent_tree'] = ($row['style_parent_tree'] != '' ? $row['style_parent_tree'] . '/' : '') . $row['style_path']; + break; + } + } + if (!$found) { - $filelist_cats[''][key($filelist_cats[$cats[$i]])] = current($filelist_cats[$cats[$i]]); - unset($filelist_cats[$cats[$i]]); + trigger_error($user->lang['STYLE_ERR_INVALID_PARENT'] . adm_back_link($update_action), E_USER_WARNING); } } - unset($cats); + else + { + $update['style_parent_tree'] = ''; + } } - } - unset($filelist); - - // Generate list of categorised theme files - $tpl_options = ''; - ksort($filelist_cats); - foreach ($filelist_cats as $category => $tpl_ary) - { - ksort($tpl_ary); - - if (!empty($category)) + else { - $tpl_options .= '<option class="sep" value="">' . $category . '</option>'; + unset($update['style_parent_id']); } - - foreach ($tpl_ary as $filename => $file) + + // Check style_active + if ($update['style_active'] != $style['style_active']) { - $selected = ($theme_file == $filename) ? ' selected="selected"' : ''; - $tpl_options .= '<option value="' . $filename . '"' . $selected . '>' . $file . '</option>'; + if (!$update['style_active'] && $config['default_style'] == $style['style_id']) + { + trigger_error($user->lang['DEACTIVATE_DEFAULT'] . adm_back_link($update_action), E_USER_WARNING); + } } - } - - $template->assign_vars(array( - 'S_EDIT_THEME' => true, - 'S_HIDDEN_FIELDS' => build_hidden_fields(array('template_file' => $theme_file)), - 'S_TEMPLATES' => $tpl_options, - - 'U_ACTION' => $this->u_action . "&action=edit&id=$theme_id&text_rows=$text_rows", - 'U_BACK' => $this->u_action, - - 'L_EDIT' => $user->lang['EDIT_THEME'], - 'L_EDIT_EXPLAIN' => $user->lang['EDIT_THEME_EXPLAIN'], - 'L_EDITOR' => $user->lang['THEME_EDITOR'], - 'L_EDITOR_HEIGHT' => $user->lang['THEME_EDITOR_HEIGHT'], - 'L_FILE' => $user->lang['THEME_FILE'], - 'L_SELECT' => $user->lang['SELECT_THEME'], - 'L_SELECTED' => $user->lang['SELECTED_THEME'], - 'L_SELECTED_FILE' => $user->lang['SELECTED_THEME_FILE'], - - 'SELECTED_TEMPLATE' => $theme_info['theme_name'], - 'TEMPLATE_FILE' => $theme_file, - 'TEMPLATE_DATA' => utf8_htmlspecialchars($theme_data), - 'TEXT_ROWS' => $text_rows, - )); - } - - /** - * Remove style/template/theme - */ - function remove($mode, $style_id) - { - global $db, $template, $user, $phpbb_root_path, $cache, $config; - - $new_id = request_var('new_id', 0); - $update = (isset($_POST['update'])) ? true : false; - $sql_where = ''; - - switch ($mode) - { - case 'style': - $sql_from = STYLES_TABLE; - $sql_select = 'style_id, style_name, template_id, theme_id'; - $sql_where = 'AND style_active = 1'; - break; - - case 'template': - $sql_from = STYLES_TEMPLATE_TABLE; - $sql_select = 'template_id, template_name, template_path'; - break; - - case 'theme': - $sql_from = STYLES_THEME_TABLE; - $sql_select = 'theme_id, theme_name, theme_path'; - break; - } - - if ($mode === 'template' && ($conflicts = $this->check_inheritance($mode, $style_id))) - { - $l_type = strtoupper($mode); - $msg = $user->lang[$l_type . '_DELETE_DEPENDENT']; - foreach ($conflicts as $id => $values) + else { - $msg .= '<br />' . $values['template_name']; + unset($update['style_active']); } - - trigger_error($msg . adm_back_link($this->u_action), E_USER_WARNING); - } - - $l_prefix = strtoupper($mode); - - $sql = "SELECT $sql_select - FROM $sql_from - WHERE {$mode}_id = $style_id"; - $result = $db->sql_query($sql); - $style_row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - if (!$style_row) - { - trigger_error($user->lang['NO_' . $l_prefix] . adm_back_link($this->u_action), E_USER_WARNING); - } - - $s_only_component = $this->display_component_options($mode, $style_row[$mode . '_id'], $style_row); - - if ($s_only_component) - { - trigger_error($user->lang['ONLY_' . $l_prefix] . adm_back_link($this->u_action), E_USER_WARNING); - } - - if ($update) - { - if ($mode == 'style') + + // Update data + if (count($update)) { - $sql = "DELETE FROM $sql_from - WHERE {$mode}_id = $style_id"; - $db->sql_query($sql); - - $sql = 'UPDATE ' . USERS_TABLE . " - SET user_style = $new_id - WHERE user_style = $style_id"; - $db->sql_query($sql); - - $sql = 'UPDATE ' . FORUMS_TABLE . " - SET forum_style = $new_id - WHERE forum_style = $style_id"; + $sql = 'UPDATE ' . STYLES_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $update) . " + WHERE style_id = $id"; $db->sql_query($sql); - - if ($style_id == $config['default_style']) - { - set_config('default_style', $new_id); - } - - // Remove the components - $components = array('template', 'theme'); - foreach ($components as $component) + + $style = array_merge($style, $update); + + if (isset($update['style_parent_id'])) { - $new_id = request_var('new_' . $component . '_id', 0); - $component_id = $style_row[$component . '_id']; - $this->remove_component($component, $component_id, $new_id, $style_id); + // Update styles tree + $styles = $this->get_styles(); + if ($this->update_styles_tree(&$styles, $style)) + { + // Something was changed in styles tree, purge all cache + $cache->purge(); + } } + add_log('admin', 'LOG_STYLE_EDIT_DETAILS', $style['style_name']); } - else + + // Update default style + $default = $request->variable('style_default', 0); + if ($default) { - $this->remove_component($mode, $style_id, $new_id); + if (!$style['style_active']) + { + trigger_error($user->lang['STYLE_DEFAULT_CHANGE_INACTIVE'] . adm_back_link($update_action), E_USER_WARNING); + } + set_config('default_style', $id); + $cache->purge(); } - - $cache->destroy('sql', STYLES_TABLE); - - add_log('admin', 'LOG_' . $l_prefix . '_DELETE', $style_row[$mode . '_name']); - $message = ($mode != 'style') ? $l_prefix . '_DELETED_FS' : $l_prefix . '_DELETED'; - trigger_error($user->lang[$message] . adm_back_link($this->u_action)); - } - - $this->page_title = 'DELETE_' . $l_prefix; - - $template->assign_vars(array( - 'S_DELETE' => true, - - 'L_TITLE' => $user->lang[$this->page_title], - 'L_EXPLAIN' => $user->lang[$this->page_title . '_EXPLAIN'], - 'L_NAME' => $user->lang[$l_prefix . '_NAME'], - 'L_REPLACE' => $user->lang['REPLACE_' . $l_prefix], - 'L_REPLACE_EXPLAIN' => $user->lang['REPLACE_' . $l_prefix . '_EXPLAIN'], - - 'U_ACTION' => $this->u_action . "&action=delete&id=$style_id", - 'U_BACK' => $this->u_action, - - 'NAME' => $style_row[$mode . '_name'], - ) - ); - - if ($mode == 'style') - { - $template->assign_vars(array( - 'S_DELETE_STYLE' => true, - )); - } - } - - /** - * Remove template/theme entry from the database - */ - function remove_component($component, $component_id, $new_id, $style_id = false) - { - global $db; - - if (($new_id == 0) || ($component === 'template' && ($conflicts = $this->check_inheritance($component, $component_id)))) - { - // We can not delete the template, as the user wants to keep the component or an other template is inheriting from this one. + + // Show styles list + $this->frontend(); return; } - - $component_in_use = array(); - if ($component != 'style') - { - $component_in_use = $this->component_in_use($component, $component_id, $style_id); - } - - if (($new_id == -1) && !empty($component_in_use)) - { - // We can not delete the component, as it is still in use - return; - } - - switch ($component) + + // Show parent styles + foreach ($list as $row) { - case 'template': - $sql_from = STYLES_TEMPLATE_TABLE; - break; - - case 'theme': - $sql_from = STYLES_THEME_TABLE; - break; + $template->assign_block_vars('parent_styles', array( + 'STYLE_ID' => $row['style_id'], + 'STYLE_NAME' => htmlspecialchars($row['style_name']), + 'LEVEL' => $row['level'], + 'SPACER' => str_repeat(' ', $row['level']), + ) + ); } - - $sql = "DELETE FROM $sql_from - WHERE {$component}_id = $component_id"; - $db->sql_query($sql); - - $sql = 'UPDATE ' . STYLES_TABLE . " - SET {$component}_id = $new_id - WHERE {$component}_id = $component_id"; - $db->sql_query($sql); + + // Show style details + $template->assign_vars(array( + 'S_STYLE_DETAILS' => true, + 'STYLE_ID' => $style['style_id'], + 'STYLE_NAME' => htmlspecialchars($style['style_name']), + 'STYLE_PATH' => htmlspecialchars($style['style_path']), + 'STYLE_COPYRIGHT' => strip_tags($style['style_copyright']), + 'STYLE_PARENT' => $style['style_parent_id'], + 'S_STYLE_ACTIVE' => $style['style_active'], + 'S_STYLE_DEFAULT' => ($style['style_id'] == $config['default_style']) + ) + ); } /** - * Display the options which can be used to replace a style/template/theme - * - * @return boolean Returns true if the component is the only component and can not be deleted. + * List installed styles */ - function display_component_options($component, $component_id, $style_row = false, $style_id = false) + function show_installed() { - global $db, $template, $user; + global $user, $template; - $is_only_component = true; - $component_in_use = array(); - if ($component != 'style') - { - $component_in_use = $this->component_in_use($component, $component_id, $style_id); - } + // Get all installed styles + $styles = $this->get_styles(); - $sql_where = ''; - switch ($component) + if (!count($styles)) { - case 'style': - $sql_from = STYLES_TABLE; - $sql_where = 'WHERE style_active = 1'; - break; - - case 'template': - $sql_from = STYLES_TEMPLATE_TABLE; - $sql_where = 'WHERE template_inherits_id <> ' . $component_id; - break; - - case 'theme': - $sql_from = STYLES_THEME_TABLE; - break; + trigger_error($user->lang['NO_MATCHING_STYLES_FOUND'] . adm_back_link($this->u_action), E_USER_WARNING); } + + usort($styles, 'acp_styles::sort_styles'); - $s_options = ''; - if (($component != 'style') && empty($component_in_use)) - { - // If it is not in use, there must be another component - $is_only_component = false; - - $sql = "SELECT {$component}_id, {$component}_name - FROM $sql_from - WHERE {$component}_id = {$component_id}"; - $result = $db->sql_query($sql); - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - $s_options .= '<option value="-1" selected="selected">' . $user->lang['DELETE_' . strtoupper($component)] . '</option>'; - $s_options .= '<option value="0">' . sprintf($user->lang['KEEP_' . strtoupper($component)], $row[$component . '_name']) . '</option>'; - } - else + // Get users + $users = $this->get_users(); + + // Add users counter to rows + foreach ($styles as &$style) { - $sql = "SELECT {$component}_id, {$component}_name - FROM $sql_from - $sql_where - ORDER BY {$component}_name ASC"; - $result = $db->sql_query($sql); - - $s_keep_option = $s_options = ''; - while ($row = $db->sql_fetchrow($result)) - { - if ($row[$component . '_id'] != $component_id) - { - $is_only_component = false; - $s_options .= '<option value="' . $row[$component . '_id'] . '">' . sprintf($user->lang['REPLACE_WITH_OPTION'], $row[$component . '_name']) . '</option>'; - } - else if ($component != 'style') - { - $s_keep_option = '<option value="0" selected="selected">' . sprintf($user->lang['KEEP_' . strtoupper($component)], $row[$component . '_name']) . '</option>'; - } - } - $db->sql_freeresult($result); - $s_options = $s_keep_option . $s_options; + $style['_users'] = isset($users[$style['style_id']]) ? $users[$style['style_id']] : 0; } + + // Set up styles list variables + // Addons should increase this number and update template variable + $this->styles_list_cols = 4; + $template->assign_var('STYLES_LIST_COLS', $this->styles_list_cols); - if (!$style_row) - { - $template->assign_var('S_REPLACE_' . strtoupper($component) . '_OPTIONS', $s_options); - } - else + // Show styles list + $this->show_styles_list(&$styles, 0, 0); + + // Show styles with invalid inherits_id + foreach ($styles as $style) { - $template->assign_var('S_REPLACE_OPTIONS', $s_options); - if ($component == 'style') + if (empty($style['_shown'])) { - $components = array('template', 'theme'); - foreach ($components as $component) - { - $this->display_component_options($component, $style_row[$component . '_id'], false, $component_id, true); - } + $style['_note'] = sprintf($user->lang['REQUIRES_STYLE'], htmlspecialchars($style['style_parent_tree'])); + $this->list_style($style, 0); } } - return $is_only_component; - } - - /** - * Check whether the component is still used by another style or component - */ - function component_in_use($component, $component_id, $style_id = false) - { - global $db; - - $component_in_use = array(); + // Add buttons + $template->assign_block_vars('extra_actions', array( + 'ACTION_NAME' => 'activate', + 'L_ACTION' => $user->lang['STYLE_ACTIVATE'], + ) + ); - if ($style_id) - { - $sql = 'SELECT style_id, style_name - FROM ' . STYLES_TABLE . " - WHERE {$component}_id = {$component_id} - AND style_id <> {$style_id} - ORDER BY style_name ASC"; - } - else - { - $sql = 'SELECT style_id, style_name - FROM ' . STYLES_TABLE . " - WHERE {$component}_id = {$component_id} - ORDER BY style_name ASC"; - } - $result = $db->sql_query($sql); - while ($row = $db->sql_fetchrow($result)) - { - $component_in_use[] = $row['style_name']; - } - $db->sql_freeresult($result); + $template->assign_block_vars('extra_actions', array( + 'ACTION_NAME' => 'deactivate', + 'L_ACTION' => $user->lang['STYLE_DEACTIVATE'], + ) + ); - if ($component === 'template' && ($conflicts = $this->check_inheritance($component, $component_id))) + if (isset($this->style_counters) && $this->style_counters['total'] > 1) { - foreach ($conflicts as $temp_id => $conflict_data) - { - $component_in_use[] = $conflict_data['template_name']; - } + $template->assign_block_vars('extra_actions', array( + 'ACTION_NAME' => 'delete', + 'L_ACTION' => $user->lang['DELETE'], + ) + ); } - - return $component_in_use; } /** - * Export style or style elements + * Show list of styles that can be installed */ - function export($mode, $style_id) + function show_available() { - global $db, $template, $user, $phpbb_root_path, $cache, $phpEx, $config; - - $update = (isset($_POST['update'])) ? true : false; - - $inc_template = request_var('inc_template', 0); - $inc_theme = request_var('inc_theme', 0); - $store = request_var('store', 0); - $format = request_var('format', ''); - - $error = array(); - $methods = array('tar'); - - $available_methods = array('tar.gz' => 'zlib', 'tar.bz2' => 'bz2', 'zip' => 'zlib'); - foreach ($available_methods as $type => $module) - { - if (!@extension_loaded($module)) - { - continue; - } - - $methods[] = $type; - } - - if (!in_array($format, $methods)) + global $user, $template; + + // Get list of styles + $styles = $this->find_available(true); + + // Show styles + if (empty($styles)) { - $format = 'tar'; + trigger_error($user->lang['NO_UNINSTALLED_STYLE'] . adm_back_link($this->u_action), E_USER_NOTICE); } + + usort($styles, 'acp_styles::sort_styles'); - switch ($mode) - { - case 'style': - if ($update && ($inc_template + $inc_theme) < 1) - { - $error[] = $user->lang['STYLE_ERR_MORE_ELEMENTS']; - } - - $name = 'style_name'; - - $sql_select = 's.style_id, s.style_name, s.style_copyright'; - $sql_select .= ($inc_template) ? ', t.*' : ', t.template_name'; - $sql_select .= ($inc_theme) ? ', c.*' : ', c.theme_name'; - $sql_from = STYLES_TABLE . ' s, ' . STYLES_TEMPLATE_TABLE . ' t, ' . STYLES_THEME_TABLE . ' c'; - $sql_where = "s.style_id = $style_id AND t.template_id = s.template_id AND c.theme_id = s.theme_id"; - - $l_prefix = 'STYLE'; - break; - - case 'template': - $name = 'template_name'; - - $sql_select = '*'; - $sql_from = STYLES_TEMPLATE_TABLE; - $sql_where = "template_id = $style_id"; - - $l_prefix = 'TEMPLATE'; - break; - - case 'theme': - $name = 'theme_name'; - - $sql_select = '*'; - $sql_from = STYLES_THEME_TABLE; - $sql_where = "theme_id = $style_id"; - - $l_prefix = 'THEME'; - break; - } - - if ($update && !sizeof($error)) + $this->styles_list_cols = 3; + $template->assign_vars(array( + 'STYLES_LIST_COLS' => $this->styles_list_cols, + 'STYLES_LIST_HIDE_COUNT' => true + ) + ); + + // Show styles + foreach ($styles as &$style) { - $sql = "SELECT $sql_select - FROM $sql_from - WHERE $sql_where"; - $result = $db->sql_query($sql); - $style_row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - if (!$style_row) - { - trigger_error($user->lang['NO_' . $l_prefix] . adm_back_link($this->u_action), E_USER_WARNING); - } - - $var_ary = array('style_id', 'style_name', 'style_copyright', 'template_id', 'template_name', 'template_path', 'template_copyright', 'template_inherits_id', 'bbcode_bitfield', 'theme_id', 'theme_name', 'theme_path', 'theme_copyright'); - - foreach ($var_ary as $var) - { - if (!isset($style_row[$var])) - { - $style_row[$var] = ''; - } - } - - $files = $data = array(); - - if ($mode == 'style') - { - $style_cfg = str_replace(array('{MODE}', '{NAME}', '{COPYRIGHT}', '{VERSION}'), array($mode, $style_row['style_name'], $style_row['style_copyright'], $config['version']), $this->style_cfg); - - $style_cfg .= (!$inc_template) ? "\nrequired_template = {$style_row['template_name']}" : ''; - $style_cfg .= (!$inc_theme) ? "\nrequired_theme = {$style_row['theme_name']}" : ''; - - $data[] = array( - 'src' => $style_cfg, - 'prefix' => 'style.cfg' - ); - - unset($style_cfg); - } - - // Export template core code - if ($mode == 'template' || $inc_template) - { - $use_template_name = $style_row['template_name']; - - // Add the inherit from variable, depending on it's use... - if ($style_row['template_inherits_id']) - { - // Get the template name - $sql = 'SELECT template_name - FROM ' . STYLES_TEMPLATE_TABLE . ' - WHERE template_id = ' . (int) $style_row['template_inherits_id']; - $result = $db->sql_query($sql); - $use_template_name = (string) $db->sql_fetchfield('template_name'); - $db->sql_freeresult($result); - } - - $template_cfg = str_replace(array('{MODE}', '{NAME}', '{COPYRIGHT}', '{VERSION}', '{INHERIT_FROM}'), array($mode, $style_row['template_name'], $style_row['template_copyright'], $config['version'], $use_template_name), $this->template_cfg); - - $template_cfg .= "\n\nbbcode_bitfield = {$style_row['bbcode_bitfield']}"; - - $data[] = array( - 'src' => $template_cfg, - 'prefix' => 'template/template.cfg' - ); - - // This is potentially nasty memory-wise ... - $files[] = array( - 'src' => "styles/{$style_row['template_path']}/template/", - 'prefix-' => "styles/{$style_row['template_path']}/", - 'prefix+' => false, - 'exclude' => 'template.cfg' - ); - unset($template_cfg); - } - - // Export theme core code - if ($mode == 'theme' || $inc_theme) - { - $theme_cfg = str_replace(array('{MODE}', '{NAME}', '{COPYRIGHT}', '{VERSION}'), array($mode, $style_row['theme_name'], $style_row['theme_copyright'], $config['version']), $this->theme_cfg); - - // Read old cfg file - $items = $cache->obtain_cfg_items($style_row); - $items = $items['theme']; - - $files[] = array( - 'src' => "styles/{$style_row['theme_path']}/theme/", - 'prefix-' => "styles/{$style_row['theme_path']}/", - 'prefix+' => false, - 'exclude' => 'theme.cfg', - ); - - $data[] = array( - 'src' => $theme_cfg, - 'prefix' => 'theme/theme.cfg', - ); - - unset($items, $theme_cfg); - } - - switch ($format) - { - case 'tar': - $ext = '.tar'; - break; - - case 'zip': - $ext = '.zip'; - break; - - case 'tar.gz': - $ext = '.tar.gz'; - break; - - case 'tar.bz2': - $ext = '.tar.bz2'; - break; - - default: - $error[] = $user->lang[$l_prefix . '_ERR_ARCHIVE']; - } - - if (!sizeof($error)) + // Check if style has a parent style in styles list + $has_parent = false; + if ($style['_inherit_name'] != '') { - include($phpbb_root_path . 'includes/functions_compress.' . $phpEx); - - if ($mode == 'style') - { - $path = preg_replace('#[^\w-]+#', '_', $style_row['style_name']); - } - else - { - $path = $style_row[$mode . '_path']; - } - - if ($format == 'zip') - { - $compress = new compress_zip('w', $phpbb_root_path . "store/$path$ext"); - } - else - { - $compress = new compress_tar('w', $phpbb_root_path . "store/$path$ext", $ext); - } - - if (sizeof($files)) - { - foreach ($files as $file_ary) - { - $compress->add_file($file_ary['src'], $file_ary['prefix-'], $file_ary['prefix+'], $file_ary['exclude']); - } - } - - if (sizeof($data)) + foreach ($styles as $parent_style) { - foreach ($data as $data_ary) + if ($parent_style['style_name'] == $style['_inherit_name'] && empty($parent_style['_shown'])) { - $compress->add_data($data_ary['src'], $data_ary['prefix']); + // Show parent style first + $has_parent = true; } } - - $compress->close(); - - add_log('admin', 'LOG_' . $l_prefix . '_EXPORT', $style_row[$mode . '_name']); - - if (!$store) - { - $compress->download($path); - @unlink("{$phpbb_root_path}store/$path$ext"); - exit; - } - - trigger_error(sprintf($user->lang[$l_prefix . '_EXPORTED'], "store/$path$ext") . adm_back_link($this->u_action)); + } + if (!$has_parent) + { + $this->list_style(&$style, 0); + $this->show_available_child_styles(&$styles, $style['style_name'], 1); } } - - $sql = "SELECT {$mode}_id, {$mode}_name - FROM " . (($mode == 'style') ? STYLES_TABLE : $sql_from) . " - WHERE {$mode}_id = $style_id"; - $result = $db->sql_query($sql); - $style_row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - if (!$style_row) + + // Show styles that do not have parent style in styles list + foreach ($styles as $style) { - trigger_error($user->lang['NO_' . $l_prefix] . adm_back_link($this->u_action), E_USER_WARNING); + if (empty($style['_shown'])) + { + $this->list_style(&$style, 0); + } } - - $this->page_title = $l_prefix . '_EXPORT'; - - $format_buttons = ''; - foreach ($methods as $method) + + // Add button + if (isset($this->style_counters) && $this->style_counters['caninstall'] > 0) { - $format_buttons .= '<label><input type="radio"' . ((!$format_buttons) ? ' id="format"' : '') . ' class="radio" value="' . $method . '" name="format"' . (($method == $format) ? ' checked="checked"' : '') . ' /> ' . $method . '</label>'; + $template->assign_block_vars('extra_actions', array( + 'ACTION_NAME' => 'install', + 'L_ACTION' => $user->lang['INSTALL_STYLES'], + ) + ); } - - $template->assign_vars(array( - 'S_EXPORT' => true, - 'S_ERROR_MSG' => (sizeof($error)) ? true : false, - 'S_STYLE' => ($mode == 'style') ? true : false, - - 'L_TITLE' => $user->lang[$this->page_title], - 'L_EXPLAIN' => $user->lang[$this->page_title . '_EXPLAIN'], - 'L_NAME' => $user->lang[$l_prefix . '_NAME'], - - 'U_ACTION' => $this->u_action . '&action=export&id=' . $style_id, - 'U_BACK' => $this->u_action, - - 'ERROR_MSG' => (sizeof($error)) ? implode('<br />', $error) : '', - 'NAME' => $style_row[$mode . '_name'], - 'FORMAT_BUTTONS' => $format_buttons) - ); } - + /** - * Display details + * Find styles available for installation + * + * @param bool $all if true, function will return all installable styles. if false, function will return only styles that can be installed + * @returns array list of styles */ - function details($mode, $style_id) + function find_available($all) { - global $template, $db, $config, $user, $safe_mode, $cache, $phpbb_root_path; - - $update = (isset($_POST['update'])) ? true : false; - $l_type = strtoupper($mode); - - $error = array(); - $element_ary = array('template' => STYLES_TEMPLATE_TABLE, 'theme' => STYLES_THEME_TABLE); - - switch ($mode) - { - case 'style': - $sql_from = STYLES_TABLE; - break; - - case 'template': - $sql_from = STYLES_TEMPLATE_TABLE; - break; - - case 'theme': - $sql_from = STYLES_THEME_TABLE; - break; - } + global $user; - $sql = "SELECT * - FROM $sql_from - WHERE {$mode}_id = $style_id"; - $result = $db->sql_query($sql); - $style_row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); + // Get list of installed styles + $installed = $this->get_styles(); - if (!$style_row) + $installed_dirs = array(); + $installed_names = array(); + foreach ($installed as $style) { - trigger_error($user->lang['NO_' . $l_type] . adm_back_link($this->u_action), E_USER_WARNING); + $installed_dirs[] = $style['style_path']; + $installed_names[$style['style_name']] = array( + 'path' => $style['style_path'], + 'id' => $style['style_id'], + 'parent' => $style['style_parent_id'], + 'tree' => (strlen($style['style_parent_tree']) ? $style['style_parent_tree'] . '/' : '') . $style['style_path'], + ); } - - $style_row['style_default'] = ($mode == 'style' && $config['default_style'] == $style_id) ? 1 : 0; - - if ($update) + + // Get list of directories + $dirs = $this->find_style_dirs(); + + // Find styles that can be installed + $styles = array(); + foreach ($dirs as $dir) { - $name = utf8_normalize_nfc(request_var('name', '', true)); - $copyright = utf8_normalize_nfc(request_var('copyright', '', true)); - - $template_id = request_var('template_id', 0); - $theme_id = request_var('theme_id', 0); - - $style_active = request_var('style_active', 0); - $style_default = request_var('style_default', 0); - - // If the admin selected the style to be the default style, but forgot to activate it... we will do it for him - if ($style_default) - { - $style_active = 1; - } - - $sql = "SELECT {$mode}_id, {$mode}_name - FROM $sql_from - WHERE {$mode}_id <> $style_id - AND LOWER({$mode}_name) = '" . $db->sql_escape(strtolower($name)) . "'"; - $result = $db->sql_query($sql); - $conflict = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - if ($mode == 'style' && (!$template_id || !$theme_id)) - { - $error[] = $user->lang['STYLE_ERR_NO_IDS']; - } - - if ($mode == 'style' && $style_row['style_active'] && !$style_active && $config['default_style'] == $style_id) - { - $error[] = $user->lang['DEACTIVATE_DEFAULT']; - } - - if (!$name || $conflict) + if (in_array($dir, $installed_dirs)) { - $error[] = $user->lang[$l_type . '_ERR_STYLE_NAME']; + // Style is already installed + continue; } - - if (!sizeof($error)) + $cfg = $this->read_style_cfg($dir); + if ($cfg === false) { - // Check length settings - if (utf8_strlen($name) > 30) - { - $error[] = $user->lang[$l_type . '_ERR_NAME_LONG']; - } - - if (utf8_strlen($copyright) > 60) - { - $error[] = $user->lang[$l_type . '_ERR_COPY_LONG']; - } + // Invalid style.cfg + continue; } - } - - if ($update && sizeof($error)) - { - $style_row = array_merge($style_row, array( - 'template_id' => $template_id, - 'theme_id' => $theme_id, - 'style_active' => $style_active, - $mode . '_name' => $name, - $mode . '_copyright' => $copyright) - ); - } - // User has submitted form and no errors have occurred - if ($update && !sizeof($error)) - { - $sql_ary = array( - $mode . '_name' => $name, - $mode . '_copyright' => $copyright + // Style should be available for installation + $parent = $cfg['parent']; + $style = array( + 'style_id' => 0, + 'style_name' => $cfg['name'], + 'style_copyright' => $cfg['copyright'], + 'style_active' => 0, + 'style_path' => $dir, + 'bbcode_bitfield' => $cfg['template_bitfield'], + 'style_parent_id' => 0, + 'style_parent_tree' => '', + // Extra values for styles list + // All extra variable start with _ so they won't be confused with data that can be added to styles table + '_inherit_name' => $parent, + '_available' => true, + '_note' => '', ); - switch ($mode) - { - case 'style': - - $sql_ary += array( - 'template_id' => (int) $template_id, - 'theme_id' => (int) $theme_id, - 'style_active' => (int) $style_active, - ); - break; - - case 'theme': - break; - - case 'template': - break; - } - - if (sizeof($sql_ary)) + // Check style inheritance + if ($parent != '') { - $sql = "UPDATE $sql_from - SET " . $db->sql_build_array('UPDATE', $sql_ary) . " - WHERE {$mode}_id = $style_id"; - $db->sql_query($sql); - - // Making this the default style? - if ($mode == 'style' && $style_default) + if (isset($installed_names[$parent])) { - set_config('default_style', $style_id); + // Parent style is installed + $row = $installed_names[$parent]; + $style['style_parent_id'] = $row['id']; + $style['style_parent_tree'] = $row['tree']; } - } - - $cache->destroy('sql', STYLES_TABLE); - - add_log('admin', 'LOG_' . $l_type . '_EDIT_DETAILS', $name); - if (sizeof($error)) - { - trigger_error(implode('<br />', $error) . adm_back_link($this->u_action), E_USER_WARNING); - } - else - { - trigger_error($user->lang[$l_type . '_DETAILS_UPDATED'] . adm_back_link($this->u_action)); - } - } - - if ($mode == 'style') - { - foreach ($element_ary as $element => $table) - { - $sql = "SELECT {$element}_id, {$element}_name - FROM $table - ORDER BY {$element}_id ASC"; - $result = $db->sql_query($sql); - - ${$element . '_options'} = ''; - while ($row = $db->sql_fetchrow($result)) + else { - $selected = ($row[$element . '_id'] == $style_row[$element . '_id']) ? ' selected="selected"' : ''; - ${$element . '_options'} .= '<option value="' . $row[$element . '_id'] . '"' . $selected . '>' . $row[$element . '_name'] . '</option>'; + // Parent style is not installed yet + $style['_available'] = false; + $style['_note'] = sprintf($user->lang['REQUIRES_STYLE'], htmlspecialchars($parent)); } - $db->sql_freeresult($result); } - } - - if ($mode == 'template') - { - $super = array(); - if (isset($style_row[$mode . '_inherits_id']) && $style_row['template_inherits_id']) + + if ($all || $style['_available']) { - $super = $this->get_super($mode, $style_row['template_id']); + $styles[] = $style; } } - $this->page_title = 'EDIT_DETAILS_' . $l_type; - - $template->assign_vars(array( - 'S_DETAILS' => true, - 'S_ERROR_MSG' => (sizeof($error)) ? true : false, - 'S_STYLE' => ($mode == 'style') ? true : false, - 'S_TEMPLATE' => ($mode == 'template') ? true : false, - 'S_THEME' => ($mode == 'theme') ? true : false, - 'S_STYLE_ACTIVE' => (isset($style_row['style_active'])) ? $style_row['style_active'] : 0, - 'S_STYLE_DEFAULT' => (isset($style_row['style_default'])) ? $style_row['style_default'] : 0, - 'S_SUPERTEMPLATE' => (isset($style_row[$mode . '_inherits_id']) && $style_row[$mode . '_inherits_id']) ? $super['template_name'] : 0, - - 'S_TEMPLATE_OPTIONS' => ($mode == 'style') ? $template_options : '', - 'S_THEME_OPTIONS' => ($mode == 'style') ? $theme_options : '', - - 'U_ACTION' => $this->u_action . '&action=details&id=' . $style_id, - 'U_BACK' => $this->u_action, - - 'L_TITLE' => $user->lang[$this->page_title], - 'L_EXPLAIN' => $user->lang[$this->page_title . '_EXPLAIN'], - 'L_NAME' => $user->lang[$l_type . '_NAME'], - - 'ERROR_MSG' => (sizeof($error)) ? implode('<br />', $error) : '', - 'NAME' => $style_row[$mode . '_name'], - 'COPYRIGHT' => $style_row[$mode . '_copyright'], - ) - ); + return $styles; } - + /** - * Load css file contents + * Show styles list + * + * @param array $styles styles list + * @param int $parent parent style id + * @param int $level style inheritance level */ - function load_css_file($path, $filename) + function show_styles_list($styles, $parent, $level) { - global $phpbb_root_path; - - $file = "{$phpbb_root_path}styles/$path/theme/$filename"; - - if (file_exists($file) && ($content = file_get_contents($file))) - { - $content = trim($content); - } - else - { - $content = ''; - } - if (defined('DEBUG')) + foreach ($styles as &$style) { - $content = "/* BEGIN @include $filename */ \n $content \n /* END @include $filename */ \n"; + if (empty($style['_shown']) && $style['style_parent_id'] == $parent) + { + $this->list_style(&$style, $level); + $this->show_styles_list(&$styles, $style['style_id'], $level + 1); + } } - - return $content; } - + /** - * Returns a string containing the value that should be used for the theme_data column in the theme database table. - * Includes contents of files loaded via @import - * - * @param array $theme_row is an associative array containing the theme's current database entry - * @param mixed $stylesheet can either be the new content for the stylesheet or false to load from the standard file - * @param string $root_path should only be used in case you want to use a different root path than "{$phpbb_root_path}styles/{$theme_row['theme_path']}" + * Show available styles tree * - * @return string Stylesheet data for theme_data column in the theme table + * @param array $styles Styles list, passed as reference + * @param string $name Name of parent style + * @param string $level Styles tree level */ - function db_theme_data($theme_row, $stylesheet = false, $root_path = '') + function show_available_child_styles($styles, $name, $level) { - global $phpbb_root_path; - - if (!$root_path) - { - $root_path = $phpbb_root_path . 'styles/' . $theme_row['theme_path']; - } - - if (!$stylesheet) - { - $stylesheet = ''; - if (file_exists($root_path . '/theme/stylesheet.css')) - { - $stylesheet = file_get_contents($root_path . '/theme/stylesheet.css'); - } - } - - // Match CSS imports - $matches = array(); - preg_match_all('/@import url\((["\'])(.*)\1\);/i', $stylesheet, $matches); - - // remove commented stylesheets (very simple parser, allows only whitespace - // around an @import statement) - preg_match_all('#/\*\s*@import url\((["\'])(.*)\1\);\s\*/#i', $stylesheet, $commented); - $matches[2] = array_diff($matches[2], $commented[2]); - - if (sizeof($matches)) + foreach ($styles as &$style) { - foreach ($matches[0] as $idx => $match) + if (empty($style['_shown']) && $style['_inherit_name'] == $name) { - if (isset($matches[2][$idx])) - { - $stylesheet = str_replace($match, acp_styles::load_css_file($theme_row['theme_path'], $matches[2][$idx]), $stylesheet); - } + $this->list_style(&$style, $level); + $this->show_available_child_styles(&$styles, $style['style_name'], $level + 1); } } - - // adjust paths - return str_replace('./', 'styles/' . $theme_row['theme_path'] . '/theme/', $stylesheet); } - + /** - * Returns an array containing all template filenames for one template that are currently cached. - * - * @param string $template_path contains the name of the template's folder in /styles/ + * Update styles tree * - * @return array of filenames that exist in /styles/$template_path/template/ (without extension!) + * @param array $styles Styles list, passed as reference + * @param array $style Current style, false if root + * @returns true if something was updated, false if not */ - function template_cache_filelist($template_path) + function update_styles_tree($styles, $style = false) { - global $phpbb_root_path, $phpEx, $user; - - $cache_prefix = 'tpl_' . str_replace('_', '-', $template_path); - - if (!($dp = @opendir("{$phpbb_root_path}cache"))) - { - trigger_error($user->lang['TEMPLATE_ERR_CACHE_READ'] . adm_back_link($this->u_action), E_USER_WARNING); - } - - $file_ary = array(); - while ($file = readdir($dp)) + $parent_id = ($style === false) ? 0 : $style['style_id']; + $parent_tree = ($style === false) ? '' : ($style['style_parent_tree'] == '' ? '' : $style['style_parent_tree']) . $style['style_path']; + $update = false; + $updated = false; + foreach ($styles as &$row) { - if ($file[0] == '.') - { - continue; - } - - if (is_file($phpbb_root_path . 'cache/' . $file) && (strpos($file, $cache_prefix) === 0)) + if ($row['style_parent_id'] == $parent_id) { - $file_ary[] = str_replace('.', '/', preg_replace('#^' . preg_quote($cache_prefix, '#') . '_(.*?)\.html\.' . $phpEx . '$#i', '\1', $file)); + if ($row['style_parent_tree'] != $parent_tree) + { + $row['style_parent_tree'] = $parent_tree; + $update = true; + } + $updated |= $this->update_styles_tree(&$styles, $row); } } - closedir($dp); - - return $file_ary; + if ($update) + { + global $db; + $sql = 'UPDATE ' . STYLES_TABLE . " + SET style_parent_tree = '" . $db->sql_escape($parent_tree) . "' + WHERE style_parent_id = {$parent_id}"; + $db->sql_query($sql); + $updated = true; + } + return $updated; } - + /** - * Destroys cached versions of template files + * Find all possible parent styles for style * - * @param array $template_row contains the template's row in the STYLES_TEMPLATE_TABLE database table - * @param mixed $file_ary is optional and may contain an array of template file names which should be refreshed in the cache. - * The file names should be the original template file names and not the cache file names. + * @param array $styles list of styles + * @param int $id id of style + * @param int $parent current parent style id + * @param int $level current tree level + * @returns array of style ids, names and levels */ - function clear_template_cache($template_row, $file_ary = false) + function find_possible_parents($styles, $id = -1, $parent = 0, $level = 0) { - global $phpbb_root_path, $phpEx, $user; - - $cache_prefix = 'tpl_' . str_replace('_', '-', $template_row['template_path']); - - if (!$file_ary || !is_array($file_ary)) - { - $file_ary = $this->template_cache_filelist($template_row['template_path']); - $log_file_list = $user->lang['ALL_FILES']; - } - else - { - $log_file_list = implode(', ', $file_ary); - } - - foreach ($file_ary as $file) - { - $file = str_replace('/', '.', $file); - - $file = "{$phpbb_root_path}cache/{$cache_prefix}_$file.html.$phpEx"; - if (file_exists($file) && is_file($file)) - { - @unlink($file); + $results = array(); + foreach ($styles as $style) + { + if ($style['style_id'] != $id && $style['style_parent_id'] == $parent) + { + $results[] = array( + 'style_id' => $style['style_id'], + 'style_name' => $style['style_name'], + 'style_path' => $style['style_path'], + 'style_parent_id' => $style['style_parent_id'], + 'style_parent_tree' => $style['style_parent_tree'], + 'level' => $level + ); + $results = array_merge($results, $this->find_possible_parents($styles, $id, $style['style_id'], $level + 1)); } } - unset($file_ary); - - add_log('admin', 'LOG_TEMPLATE_CACHE_CLEARED', $template_row['template_name'], $log_file_list); + return $results; } - + /** - * Install Style/Template/Theme + * Show item in styles list + * + * @param array $style style row + * @param array $level style inheritance level */ - function install($mode) + function list_style($style, $level) { - global $phpbb_root_path, $phpEx, $config, $db, $cache, $user, $template; - - $l_type = strtoupper($mode); + global $template, $config, $db, $user, $phpbb_root_path, $phpEx; + + // Mark row as shown + if (!empty($style['_shown'])) return; + $style['_shown'] = true; + + // Generate template variables + $actions = array(); + $row = array( + // Style data + 'STYLE_ID' => $style['style_id'], + 'STYLE_NAME' => htmlspecialchars($style['style_name']), + 'STYLE_PATH' => htmlspecialchars($style['style_path']), + 'STYLE_COPYRIGHT' => strip_tags($style['style_copyright']), + 'STYLE_ACTIVE' => $style['style_active'], + + // Additional data + 'DEFAULT' => ($style['style_id'] && $style['style_id'] == $config['default_style']), + 'USERS' => $style['_users'], + 'LEVEL' => $level, + 'PADDING' => (4 + 16 * $level), + 'SHOW_COPYRIGHT' => ($style['style_id']) ? false : true, + 'STYLE_PATH_FULL' => htmlspecialchars($this->styles_path_absolute . '/' . $style['style_path']) . '/', + + // Comment to show below style + 'COMMENT' => (isset($style['_note'])) ? $style['_note'] : '', + + // The following variables should be used by hooks to add custom HTML code + 'EXTRA' => '', + 'EXTRA_OPTIONS' => '' + ); + + // Status specific data + if ($style['style_id']) + { + // Style is installed + + // Details + $actions[] = array( + 'U_ACTION' => $this->u_action . '&action=details&id=' . $style['style_id'], + 'L_ACTION' => $user->lang['DETAILS'] + ); - $error = $installcfg = $style_row = array(); - $root_path = $cfg_file = ''; - $element_ary = array('template' => STYLES_TEMPLATE_TABLE, 'theme' => STYLES_THEME_TABLE); + // Activate + $actions[] = array( + 'U_ACTION' => $this->u_action . '&action=' . ($style['style_active'] ? 'de' : '') . 'activate&id=' . $style['style_id'], + 'L_ACTION' => $user->lang['STYLE_' . ($style['style_active'] ? 'DE' : '') . 'ACTIVATE'] + ); - $install_path = request_var('path', ''); - $update = (isset($_POST['update'])) ? true : false; +/* // Export + $actions[] = array( + 'U_ACTION' => $this->u_action . '&action=export&id=' . $style['style_id'], + 'L_ACTION' => $user->lang['EXPORT'] + ); */ - // Installing, obtain cfg file contents - if ($install_path) + // Delete + $actions[] = array( + 'U_ACTION' => $this->u_action . '&action=delete&id=' . $style['style_id'], + 'L_ACTION' => $user->lang['DELETE'] + ); + + // Preview + $actions[] = array( + 'U_ACTION' => append_sid("{$phpbb_root_path}index.$phpEx", 'style=' . $style['style_id']), + 'L_ACTION' => $user->lang['PREVIEW'] + ); + } + else { - $root_path = $phpbb_root_path . 'styles/' . $install_path . '/'; - $cfg_file = ($mode == 'style') ? "$root_path$mode.cfg" : "$root_path$mode/$mode.cfg"; - - if (!file_exists($cfg_file)) + // Style is not installed + if (empty($style['_available'])) { - $error[] = $user->lang[$l_type . '_ERR_NOT_' . $l_type]; + $actions[] = array( + 'HTML' => $user->lang['CANNOT_BE_INSTALLED'] + ); } else { - $installcfg = parse_cfg_file($cfg_file); - } - } - - // Installing - if (sizeof($installcfg)) - { - $name = $installcfg['name']; - $copyright = $installcfg['copyright']; - $version = $installcfg['version']; - - $style_row = array( - $mode . '_id' => 0, - $mode . '_name' => '', - $mode . '_copyright' => '' - ); - - switch ($mode) - { - case 'style': - - $style_row = array( - 'style_id' => 0, - 'style_name' => $installcfg['name'], - 'style_copyright' => $installcfg['copyright'] - ); - - $reqd_template = (isset($installcfg['required_template'])) ? $installcfg['required_template'] : false; - $reqd_theme = (isset($installcfg['required_theme'])) ? $installcfg['required_theme'] : false; - - // Check to see if each element is already installed, if it is grab the id - foreach ($element_ary as $element => $table) - { - $style_row = array_merge($style_row, array( - $element . '_id' => 0, - $element . '_name' => '', - $element . '_copyright' => '') - ); - - $this->test_installed($element, $error, (${'reqd_' . $element}) ? $phpbb_root_path . 'styles/' . $reqd_template . '/' : $root_path, ${'reqd_' . $element}, $style_row[$element . '_id'], $style_row[$element . '_name'], $style_row[$element . '_copyright']); - - if (!$style_row[$element . '_name']) - { - $style_row[$element . '_name'] = $reqd_template; - } - - // Merge other information to installcfg... if present - $cfg_file = $phpbb_root_path . 'styles/' . $install_path . '/' . $element . '/' . $element . '.cfg'; - - if (file_exists($cfg_file)) - { - $cfg_contents = parse_cfg_file($cfg_file); - - // Merge only specific things. We may need them later. - foreach (array('inherit_from') as $key) - { - if (!empty($cfg_contents[$key]) && !isset($installcfg[$key])) - { - $installcfg[$key] = $cfg_contents[$key]; - } - } - } - } - - break; - - case 'template': - $this->test_installed('template', $error, $root_path, false, $style_row['template_id'], $style_row['template_name'], $style_row['template_copyright']); - break; - - case 'theme': - $this->test_installed('theme', $error, $root_path, false, $style_row['theme_id'], $style_row['theme_name'], $style_row['theme_copyright']); - break; + $actions[] = array( + 'U_ACTION' => $this->u_action . '&action=install&dir=' . urlencode($style['style_path']), + 'L_ACTION' => $user->lang['INSTALL_STYLE'] + ); } } - else + + // todo: add hook + + // Assign template variables + $template->assign_block_vars('styles_list', $row); + foreach($actions as $action) { - trigger_error($user->lang['NO_' . $l_type] . adm_back_link($this->u_action), E_USER_WARNING); + $template->assign_block_vars('styles_list.actions', $action); } - - $style_row['style_active'] = request_var('style_active', 1); - $style_row['style_default'] = request_var('style_default', 0); - - // User has submitted form and no errors have occurred - if ($update && !sizeof($error)) + + // Increase counters + $counter = ($style['style_id']) ? ($style['style_active'] ? 'active' : 'inactive') : (empty($style['_available']) ? 'cannotinstall' : 'caninstall'); + if (!isset($this->style_counters)) { - if ($mode == 'style') - { - foreach ($element_ary as $element => $table) - { - ${$element . '_root_path'} = (${'reqd_' . $element}) ? $phpbb_root_path . 'styles/' . ${'reqd_' . $element} . '/' : false; - ${$element . '_path'} = (${'reqd_' . $element}) ? ${'reqd_' . $element} : false; - } - $this->install_style($error, 'install', $root_path, $style_row['style_id'], $style_row['style_name'], $install_path, $style_row['style_copyright'], $style_row['style_active'], $style_row['style_default'], $style_row, $template_root_path, $template_path, $theme_root_path, $theme_path); - } - else - { - $this->install_element($mode, $error, 'install', $root_path, $style_row[$mode . '_id'], $style_row[$mode . '_name'], $install_path, $style_row[$mode . '_copyright']); - } - - if (!sizeof($error)) - { - $cache->destroy('sql', STYLES_TABLE); - - trigger_error($user->lang[$l_type . '_ADDED'] . adm_back_link($this->u_action)); - } + $this->style_counters = array( + 'total' => 0, + 'active' => 0, + 'inactive' => 0, + 'caninstall' => 0, + 'cannotinstall' => 0 + ); } - - $this->page_title = 'INSTALL_' . $l_type; - + $this->style_counters[$counter] ++; + $this->style_counters['total'] ++; + } + + /** + * Show welcome message + * + * @param string $title main title + * @param string $description page description + */ + function welcome_message($title, $description) + { + global $user, $template; $template->assign_vars(array( - 'S_DETAILS' => true, - 'S_INSTALL' => true, - 'S_ERROR_MSG' => (sizeof($error)) ? true : false, - 'S_LOCATION' => (isset($installcfg['inherit_from']) && $installcfg['inherit_from']) ? false : true, - 'S_STYLE' => ($mode == 'style') ? true : false, - 'S_TEMPLATE' => ($mode == 'template') ? true : false, - 'S_SUPERTEMPLATE' => (isset($installcfg['inherit_from'])) ? $installcfg['inherit_from'] : '', - 'S_THEME' => ($mode == 'theme') ? true : false, - - 'S_STYLE_ACTIVE' => (isset($style_row['style_active'])) ? $style_row['style_active'] : 0, - 'S_STYLE_DEFAULT' => (isset($style_row['style_default'])) ? $style_row['style_default'] : 0, - - 'U_ACTION' => $this->u_action . "&action=install&path=" . urlencode($install_path), - 'U_BACK' => $this->u_action, - - 'L_TITLE' => $user->lang[$this->page_title], - 'L_EXPLAIN' => $user->lang[$this->page_title . '_EXPLAIN'], - 'L_NAME' => $user->lang[$l_type . '_NAME'], - - 'ERROR_MSG' => (sizeof($error)) ? implode('<br />', $error) : '', - 'NAME' => $style_row[$mode . '_name'], - 'COPYRIGHT' => $style_row[$mode . '_copyright'], - 'TEMPLATE_NAME' => ($mode == 'style') ? $style_row['template_name'] : '', - 'THEME_NAME' => ($mode == 'style') ? $style_row['theme_name'] : '') + 'L_TITLE' => (isset($user->lang[$title])) ? $user->lang[$title] : $title, + 'L_EXPLAIN' => (isset($user->lang[$description])) ? $user->lang[$description] : $description + ) ); } - + /** - * Add new style + * Find all directories that have styles + * + * @returns array of directory names */ - function add($mode) + function find_style_dirs() { - global $phpbb_root_path, $phpEx, $config, $db, $cache, $user, $template; - - $l_type = strtoupper($mode); - $element_ary = array('template' => STYLES_TEMPLATE_TABLE, 'theme' => STYLES_THEME_TABLE); - $error = array(); - - $style_row = array( - $mode . '_name' => utf8_normalize_nfc(request_var('name', '', true)), - $mode . '_copyright' => utf8_normalize_nfc(request_var('copyright', '', true)), - 'template_id' => 0, - 'theme_id' => 0, - 'style_active' => request_var('style_active', 1), - 'style_default' => request_var('style_default', 0), - ); - - $basis = request_var('basis', 0); - $update = (isset($_POST['update'])) ? true : false; - - if ($basis) - { - switch ($mode) - { - case 'style': - $sql_select = 'template_id, theme_id'; - $sql_from = STYLES_TABLE; - break; - - case 'template': - $sql_select = 'template_id'; - $sql_from = STYLES_TEMPLATE_TABLE; - break; - - case 'theme': - $sql_select = 'theme_id'; - $sql_from = STYLES_THEME_TABLE; - break; - } - - $sql = "SELECT $sql_select - FROM $sql_from - WHERE {$mode}_id = $basis"; - $result = $db->sql_query($sql); - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - if (!$row) - { - $error[] = $user->lang['NO_' . $l_type]; - } - - if (!sizeof($error)) - { - $style_row['template_id'] = (isset($row['template_id'])) ? $row['template_id'] : $style_row['template_id']; - $style_row['theme_id'] = (isset($row['theme_id'])) ? $row['theme_id'] : $style_row['theme_id']; - } - } - - if ($update) - { - $style_row['template_id'] = request_var('template_id', $style_row['template_id']); - $style_row['theme_id'] = request_var('theme_id', $style_row['theme_id']); - - if ($mode == 'style' && (!$style_row['template_id'] || !$style_row['theme_id'])) - { - $error[] = $user->lang['STYLE_ERR_NO_IDS']; - } - } - - // User has submitted form and no errors have occurred - if ($update && !sizeof($error)) - { - if ($mode == 'style') - { - $style_row['style_id'] = 0; - - $this->install_style($error, 'add', '', $style_row['style_id'], $style_row['style_name'], '', $style_row['style_copyright'], $style_row['style_active'], $style_row['style_default'], $style_row); - } - - if (!sizeof($error)) - { - $cache->destroy('sql', STYLES_TABLE); - - trigger_error($user->lang[$l_type . '_ADDED'] . adm_back_link($this->u_action)); - } - } + $styles = array(); - if ($mode == 'style') + $dp = @opendir($this->styles_path); + if ($dp) { - foreach ($element_ary as $element => $table) + while (($file = readdir($dp)) !== false) { - $sql = "SELECT {$element}_id, {$element}_name - FROM $table - ORDER BY {$element}_id ASC"; - $result = $db->sql_query($sql); + $dir = $this->styles_path . $file; + if ($file[0] == '.' || !is_dir($dir)) + { + continue; + } - ${$element . '_options'} = ''; - while ($row = $db->sql_fetchrow($result)) + if (file_exists("{$dir}/style.cfg")) { - $selected = ($row[$element . '_id'] == $style_row[$element . '_id']) ? ' selected="selected"' : ''; - ${$element . '_options'} .= '<option value="' . $row[$element . '_id'] . '"' . $selected . '>' . $row[$element . '_name'] . '</option>'; + $styles[] = $file; } - $db->sql_freeresult($result); } + closedir($dp); } - $this->page_title = 'ADD_' . $l_type; - - $template->assign_vars(array( - 'S_DETAILS' => true, - 'S_ADD' => true, - 'S_ERROR_MSG' => (sizeof($error)) ? true : false, - 'S_STYLE' => ($mode == 'style') ? true : false, - 'S_TEMPLATE' => ($mode == 'template') ? true : false, - 'S_THEME' => ($mode == 'theme') ? true : false, - 'S_BASIS' => ($basis) ? true : false, - - 'S_STYLE_ACTIVE' => (isset($style_row['style_active'])) ? $style_row['style_active'] : 0, - 'S_STYLE_DEFAULT' => (isset($style_row['style_default'])) ? $style_row['style_default'] : 0, - 'S_TEMPLATE_OPTIONS' => ($mode == 'style') ? $template_options : '', - 'S_THEME_OPTIONS' => ($mode == 'style') ? $theme_options : '', - - 'U_ACTION' => $this->u_action . '&action=add&basis=' . $basis, - 'U_BACK' => $this->u_action, - - 'L_TITLE' => $user->lang[$this->page_title], - 'L_EXPLAIN' => $user->lang[$this->page_title . '_EXPLAIN'], - 'L_NAME' => $user->lang[$l_type . '_NAME'], - - 'ERROR_MSG' => (sizeof($error)) ? implode('<br />', $error) : '', - 'NAME' => $style_row[$mode . '_name'], - 'COPYRIGHT' => $style_row[$mode . '_copyright']) - ); - + return $styles; } - + /** - - $reqd_template = (isset($installcfg['required_template'])) ? $installcfg['required_template'] : false; - $reqd_theme = (isset($installcfg['required_theme'])) ? $installcfg['required_theme'] : false; - - // Check to see if each element is already installed, if it is grab the id - foreach ($element_ary as $element => $table) - { - $style_row = array_merge($style_row, array( - $element . '_id' => 0, - $element . '_name' => '', - $element . '_copyright' => '') - ); - - $this->test_installed($element, $error, $root_path, ${'reqd_' . $element}, $style_row[$element . '_id'], $style_row[$element . '_name'], $style_row[$element . '_copyright']); - * Is this element installed? If not, grab its cfg details + * Sort styles */ - function test_installed($element, &$error, $root_path, $reqd_name, &$id, &$name, &$copyright) + function sort_styles($style1, $style2) { - global $db, $user; - - switch ($element) - { - case 'template': - $sql_from = STYLES_TEMPLATE_TABLE; - break; - - case 'theme': - $sql_from = STYLES_THEME_TABLE; - break; - } - - $l_element = strtoupper($element); - - $chk_name = ($reqd_name !== false) ? $reqd_name : $name; - - $sql = "SELECT {$element}_id, {$element}_name - FROM $sql_from - WHERE {$element}_name = '" . $db->sql_escape($chk_name) . "'"; - $result = $db->sql_query($sql); - - if ($row = $db->sql_fetchrow($result)) + if ($style1['style_active'] != $style2['style_active']) { - $name = $row[$element . '_name']; - $id = $row[$element . '_id']; + return ($style1['style_active']) ? -1 : 1; } - else + if (isset($style1['_available']) && $style1['_available'] != $style2['_available']) { - if (!($cfg = @file("$root_path$element/$element.cfg"))) - { - $error[] = sprintf($user->lang['REQUIRES_' . $l_element], $reqd_name); - return false; - } - - $cfg = parse_cfg_file("$root_path$element/$element.cfg", $cfg); - - $name = $cfg['name']; - $copyright = $cfg['copyright']; - $id = 0; - - unset($cfg); + return ($style1['_available']) ? -1 : 1; } - $db->sql_freeresult($result); + return strcasecmp(isset($style1['style_name']) ? $style1['style_name'] : $style1['name'], isset($style2['style_name']) ? $style2['style_name'] : $style2['name']); } - + /** - * Install/Add style + * Read style configuration file + * + * @param string $dir style directory + * @returns array of style data + * @returns false on error */ - function install_style(&$error, $action, $root_path, &$id, $name, $path, $copyright, $active, $default, &$style_row, $template_root_path = false, $template_path = false, $theme_root_path = false, $theme_path = false) + function read_style_cfg($dir) { - global $config, $db, $user; - - $element_ary = array('template', 'theme'); - - if (!$name) - { - $error[] = $user->lang['STYLE_ERR_STYLE_NAME']; - } - - // Check length settings - if (utf8_strlen($name) > 30) - { - $error[] = $user->lang['STYLE_ERR_NAME_LONG']; - } - - if (utf8_strlen($copyright) > 60) + static $required = array('name', 'version', 'copyright'); + $cfg = parse_cfg_file($this->styles_path . $dir . '/style.cfg'); + + // Check if it is a valid file + foreach ($required as $key) { - $error[] = $user->lang['STYLE_ERR_COPY_LONG']; + if (!isset($cfg[$key])) + { + return false; + } } - - // Check if the name already exist - $sql = 'SELECT style_id - FROM ' . STYLES_TABLE . " - WHERE style_name = '" . $db->sql_escape($name) . "'"; - $result = $db->sql_query($sql); - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - if ($row) + + // Check data + if (!isset($cfg['parent']) || !is_string($cfg['parent']) || $cfg['parent'] == $cfg['name']) { - $error[] = $user->lang['STYLE_ERR_NAME_EXIST']; + $cfg['parent'] = ''; } - - if (sizeof($error)) + if (!isset($cfg['template_bitfield'])) { - return false; + $cfg['template_bitfield'] = $this->default_bitfield(); } - - foreach ($element_ary as $element) + + return $cfg; + } + + /** + * Install style + * + * @param $style style data + * @returns int style id + */ + function install_style($style) + { + global $db; + + // Generate row + $sql_ary = array(); + foreach ($style as $key => $value) { - // Zero id value ... need to install element ... run usual checks - // and do the install if necessary - if (!$style_row[$element . '_id']) + if ($key != 'style_id' && substr($key, 0, 1) != '_') { - $this->install_element($element, $error, $action, (${$element . '_root_path'}) ? ${$element . '_root_path'} : $root_path, $style_row[$element . '_id'], $style_row[$element . '_name'], (${$element . '_path'}) ? ${$element . '_path'} : $path, $style_row[$element . '_copyright']); + $sql_ary[$key] = $value; } } - - if (!$style_row['template_id'] || !$style_row['theme_id']) - { - $error[] = $user->lang['STYLE_ERR_NO_IDS']; - } - - if (sizeof($error)) - { - return false; - } - + + // Add to database $db->sql_transaction('begin'); - $sql_ary = array( - 'style_name' => $name, - 'style_copyright' => $copyright, - 'style_active' => (int) $active, - 'template_id' => (int) $style_row['template_id'], - 'theme_id' => (int) $style_row['theme_id'], - ); - $sql = 'INSERT INTO ' . STYLES_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary); $db->sql_query($sql); $id = $db->sql_nextid(); - if ($default) - { - $sql = 'UPDATE ' . USERS_TABLE . " - SET user_style = $id - WHERE user_style = " . $config['default_style']; - $db->sql_query($sql); - - set_config('default_style', $id); - } - $db->sql_transaction('commit'); - add_log('admin', 'LOG_STYLE_ADD', $name); + add_log('admin', 'LOG_STYLE_ADD', $sql_ary['style_name']); + + return $id; } /** - * Install/add an element, doing various checks as we go + * Lists all styles + * + * @returns array of rows with styles data */ - function install_element($mode, &$error, $action, $root_path, &$id, $name, $path, $copyright) + function get_styles() { - global $phpbb_root_path, $db, $user; - - // we parse the cfg here (again) - $cfg_data = parse_cfg_file("$root_path$mode/$mode.cfg"); - - switch ($mode) - { - case 'template': - $sql_from = STYLES_TEMPLATE_TABLE; - break; + global $db; + + $sql = 'SELECT * + FROM ' . STYLES_TABLE; + $result = $db->sql_query($sql); - case 'theme': - $sql_from = STYLES_THEME_TABLE; - break; - } + $rows = $db->sql_fetchrowset($result); + $db->sql_freeresult($result); - $l_type = strtoupper($mode); + return $rows; + } - if (!$name) - { - $error[] = $user->lang[$l_type . '_ERR_STYLE_NAME']; - } + /** + * Count users for each style + * + * @returns array of styles in following format: [style_id] = number of users + */ + function get_users() + { + global $db; - // Check length settings - if (utf8_strlen($name) > 30) - { - $error[] = $user->lang[$l_type . '_ERR_NAME_LONG']; - } + $sql = 'SELECT user_style, COUNT(user_style) AS style_count + FROM ' . USERS_TABLE . ' + GROUP BY user_style'; + $result = $db->sql_query($sql); - if (utf8_strlen($copyright) > 60) + $style_count = array(); + while ($row = $db->sql_fetchrow($result)) { - $error[] = $user->lang[$l_type . '_ERR_COPY_LONG']; + $style_count[$row['user_style']] = $row['style_count']; } - - // Check if the name already exist - $sql = "SELECT {$mode}_id - FROM $sql_from - WHERE {$mode}_name = '" . $db->sql_escape($name) . "'"; + $db->sql_freeresult($result); + + return $style_count; + } + + /** + * Delete style + * + * @param array $style Style data + * @returns true on success, error message on error + */ + function delete_style($style) + { + global $db, $user; + + $id = $style['style_id']; + $path = $style['style_path']; + + // Check if style has child styles + $sql = 'SELECT style_id + FROM ' . STYLES_TABLE . ' + WHERE style_parent_id = ' . $id . " OR style_parent_tree = '" . $db->sql_escape($path) . "'"; $result = $db->sql_query($sql); - $row = $db->sql_fetchrow($result); + + $conflict = $db->sql_fetchrow($result); $db->sql_freeresult($result); - if ($row) - { - // If it exist, we just use the style on installation - if ($action == 'install') - { - $id = $row[$mode . '_id']; - return false; - } - - $error[] = $user->lang[$l_type . '_ERR_NAME_EXIST']; - } - - if (isset($cfg_data['inherit_from']) && $cfg_data['inherit_from']) - { - if ($mode === 'template') - { - $select_bf = ', bbcode_bitfield'; - } - else - { - $select_bf = ''; - } - - $sql = "SELECT {$mode}_id, {$mode}_name, {$mode}_path $select_bf - FROM $sql_from - WHERE {$mode}_name = '" . $db->sql_escape($cfg_data['inherit_from']) . "' - AND {$mode}_inherits_id = 0"; - $result = $db->sql_query($sql); - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - if (!$row) - { - $error[] = sprintf($user->lang[$l_type . '_ERR_REQUIRED_OR_INCOMPLETE'], $cfg_data['inherit_from']); - } - else - { - $inherit_id = $row["{$mode}_id"]; - $inherit_path = $row["{$mode}_path"]; - $inherit_bf = ($mode === 'template') ? $row["bbcode_bitfield"] : false; - } - } - else - { - $inherit_id = 0; - $inherit_path = ''; - $inherit_bf = false; - } - - if (sizeof($error)) + if ($conflict !== false) { - return false; + return sprintf($user->lang['STYLE_DELETE_DEPENDENT'], $style['style_name']); } + + // Change default style for users + $sql = 'UPDATE ' . USERS_TABLE . ' + SET user_style = 0 + WHERE user_style = ' . $id; + $db->sql_query($sql); + + // Delete style + $sql = 'DELETE FROM ' . STYLES_TABLE . ' + WHERE style_id = ' . $id; + $db->sql_query($sql); + return true; + } - $sql_ary = array( - $mode . '_name' => $name, - $mode . '_copyright' => $copyright, - $mode . '_path' => $path, - ); + /** + * Delete all files in style directory + * + * @param string $path Style directory + * @param string $dir Directory to remove inside style's directory + * @returns true on success, false on error + */ + function delete_style_files($path, $dir = '') + { + $dirname = $this->styles_path . $path . $dir; + $result = true; + + $dp = @opendir($dirname); - switch ($mode) + if ($dp) { - case 'template': - // We check if the template author defined a different bitfield - if (!empty($cfg_data['template_bitfield'])) + while (($file = readdir($dp)) !== false) + { + if ($file == '.' || $file == '..') { - $sql_ary['bbcode_bitfield'] = $cfg_data['template_bitfield']; + continue; } - else if ($inherit_bf) + $filename = $dirname . '/' . $file; + if (is_dir($filename)) { - $sql_ary['bbcode_bitfield'] = $inherit_bf; + if (!$this->delete_style_files($path, $dir . '/' . $file)) + { + $result = false; + } } else { - $sql_ary['bbcode_bitfield'] = $this->template_bitfield; - } - - if (isset($cfg_data['inherit_from']) && $cfg_data['inherit_from']) - { - $sql_ary += array( - 'template_inherits_id' => $inherit_id, - 'template_inherit_path' => $inherit_path, - ); + if (!@unlink($filename)) + { + $result = false; + } } - break; - - case 'theme': - break; + } + closedir($dp); } - - $db->sql_transaction('begin'); - - $sql = "INSERT INTO $sql_from - " . $db->sql_build_array('INSERT', $sql_ary); - $db->sql_query($sql); - - $id = $db->sql_nextid(); - - $db->sql_transaction('commit'); - - add_log('admin', 'LOG_' . $l_type . '_ADD_FS', $name); + if (!@rmdir($dirname)) + { + return false; + } + + return $result; } - + /** - * Checks downwards dependencies + * Get list of items from posted data * - * @access public - * @param string $mode The element type to check - only template is supported - * @param int $id The template id - * @returns false if no component inherits, array with name, path and id for each subtemplate otherwise + * @param string $name Variable name + * @param $default Default value for array: string or number + * @param bool $error If true, error will be triggered if list is empty + * @returns array of items */ - function check_inheritance($mode, $id) + function request_vars($name, $default, $error = false) { - global $db; - - $l_type = strtoupper($mode); - - switch ($mode) - { - case 'template': - $sql_from = STYLES_TEMPLATE_TABLE; - break; - - case 'theme': - $sql_from = STYLES_THEME_TABLE; - break; - } + global $request, $user; - $sql = "SELECT {$mode}_id, {$mode}_name, {$mode}_path - FROM $sql_from - WHERE {$mode}_inherits_id = " . (int) $id; - $result = $db->sql_query($sql); + $item = $request->variable($name, $default); + $items = $request->variable($name . 's', array($default)); - $names = array(); - while ($row = $db->sql_fetchrow($result)) + if (count($items) == 1 && $items[0] == $default) { - - $names[$row["{$mode}_id"]] = array( - "{$mode}_id" => $row["{$mode}_id"], - "{$mode}_name" => $row["{$mode}_name"], - "{$mode}_path" => $row["{$mode}_path"], - ); + $items = array(); } - $db->sql_freeresult($result); - if (sizeof($names)) + if ($item != $default && !count($items)) { - return $names; + $items[] = $item; } - else + + if ($error && !count($items)) { - return false; + trigger_error($user->lang['NO_MATCHING_STYLES_FOUND'] . adm_back_link($this->u_action), E_USER_WARNING); } + + return $items; } /** - * Checks upwards dependencies + * Generates hardcoded bitfield * - * @access public - * @param string $mode The element type to check - only template is supported - * @param int $id The template id - * @returns false if the component does not inherit, array with name, path and id otherwise + * @returns bitfield string */ - function get_super($mode, $id) + function default_bitfield() { - global $db; - - $l_type = strtoupper($mode); - - switch ($mode) - { - case 'template': - $sql_from = STYLES_TEMPLATE_TABLE; - break; - - case 'theme': - $sql_from = STYLES_THEME_TABLE; - break; - } - - $sql = "SELECT {$mode}_inherits_id - FROM $sql_from - WHERE {$mode}_id = " . (int) $id; - $result = $db->sql_query_limit($sql, 1); - - if ($row = $db->sql_fetchrow($result)) - { - $db->sql_freeresult($result); - } - else + static $value; + if(isset($value)) { - return false; + return $value; } - - $super_id = $row["{$mode}_inherits_id"]; - - $sql = "SELECT {$mode}_id, {$mode}_name, {$mode}_path - FROM $sql_from - WHERE {$mode}_id = " . (int) $super_id; - - $result = $db->sql_query_limit($sql, 1); - if ($row = $db->sql_fetchrow($result)) - { - $db->sql_freeresult($result); - return $row; - } - - return false; + + // Hardcoded template bitfield to add for new templates + $bitfield = new bitfield(); + $bitfield->set(0); + $bitfield->set(1); + $bitfield->set(2); + $bitfield->set(3); + $bitfield->set(4); + $bitfield->set(8); + $bitfield->set(9); + $bitfield->set(11); + $bitfield->set(12); + $value = $bitfield->get_base64(); + return $value; } + } diff --git a/phpBB/includes/acp/info/acp_styles.php b/phpBB/includes/acp/info/acp_styles.php index 221371c4cb..3137c4781b 100644 --- a/phpBB/includes/acp/info/acp_styles.php +++ b/phpBB/includes/acp/info/acp_styles.php @@ -17,11 +17,11 @@ class acp_styles_info return array( 'filename' => 'acp_styles', 'title' => 'ACP_CAT_STYLES', - 'version' => '1.0.0', + 'version' => '2.0.0', 'modes' => array( 'style' => array('title' => 'ACP_STYLES', 'auth' => 'acl_a_styles', 'cat' => array('ACP_STYLE_MANAGEMENT')), - 'template' => array('title' => 'ACP_TEMPLATES', 'auth' => 'acl_a_styles', 'cat' => array('ACP_STYLE_COMPONENTS')), - 'theme' => array('title' => 'ACP_THEMES', 'auth' => 'acl_a_styles', 'cat' => array('ACP_STYLE_COMPONENTS')), + 'install' => array('title' => 'ACP_STYLES_INSTALL', 'auth' => 'acl_a_styles', 'cat' => array('ACP_STYLE_MANAGEMENT')), + 'cache' => array('title' => 'ACP_STYLES_CACHE', 'auth' => 'acl_a_styles', 'cat' => array('ACP_STYLE_MANAGEMENT')), ), ); } diff --git a/phpBB/includes/bbcode.php b/phpBB/includes/bbcode.php index 60274a308d..5e3bfed5ec 100644 --- a/phpBB/includes/bbcode.php +++ b/phpBB/includes/bbcode.php @@ -132,12 +132,11 @@ class bbcode { $this->template_bitfield = new bitfield($user->theme['bbcode_bitfield']); - $template_locator = new phpbb_template_locator(); - $template_path_provider = new phpbb_template_extension_path_provider($phpbb_extension_manager, new phpbb_template_path_provider()); - $template = new phpbb_template($phpbb_root_path, $phpEx, $config, $user, $template_locator, $template_path_provider); - $template->set_template(); - $template_locator->set_filenames(array('bbcode.html' => 'bbcode.html')); - $this->template_filename = $template_locator->get_source_file_for_handle('bbcode.html'); + $style = new phpbb_style($phpbb_root_path, $phpEx, $config, $user, $phpbb_extension_manager); + $style->set_style(); + $template = $style->template; + $template->set_filenames(array('bbcode.html' => 'bbcode.html')); + $this->template_filename = $style->locator->get_source_file_for_handle('bbcode.html'); } $bbcode_ids = $rowset = $sql = array(); diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index afd901a296..99740b753b 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -3117,9 +3117,9 @@ function parse_cfg_file($filename, $lines = false) $parsed_items[$key] = $value; } - if (isset($parsed_items['inherit_from']) && isset($parsed_items['name']) && $parsed_items['inherit_from'] == $parsed_items['name']) + if (isset($parsed_items['parent']) && isset($parsed_items['name']) && $parsed_items['parent'] == $parsed_items['name']) { - unset($parsed_items['inherit_from']); + unset($parsed_items['parent']); } return $parsed_items; @@ -4768,9 +4768,9 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0 'S_SEARCH_HIDDEN_FIELDS' => build_hidden_fields($s_search_hidden_fields), 'T_ASSETS_PATH' => "{$web_path}assets", - 'T_THEME_PATH' => "{$web_path}styles/" . rawurlencode($user->theme['theme_path']) . '/theme', - 'T_TEMPLATE_PATH' => "{$web_path}styles/" . rawurlencode($user->theme['template_path']) . '/template', - 'T_SUPER_TEMPLATE_PATH' => (isset($user->theme['template_inherit_path']) && $user->theme['template_inherit_path']) ? "{$web_path}styles/" . rawurlencode($user->theme['template_inherit_path']) . '/template' : "{$web_path}styles/" . rawurlencode($user->theme['template_path']) . '/template', + 'T_THEME_PATH' => "{$web_path}styles/" . rawurlencode($user->theme['style_path']) . '/theme', + 'T_TEMPLATE_PATH' => "{$web_path}styles/" . rawurlencode($user->theme['style_path']) . '/template', + 'T_SUPER_TEMPLATE_PATH' => ($user->theme['style_parent_id']) ? "{$web_path}styles/" . rawurlencode($user->theme['style_parent_tree']) . '/template' : "{$web_path}styles/" . rawurlencode($user->theme['style_path']) . '/template', 'T_IMAGES_PATH' => "{$web_path}images/", 'T_SMILIES_PATH' => "{$web_path}{$config['smilies_path']}/", 'T_AVATAR_PATH' => "{$web_path}{$config['avatar_path']}/", @@ -4778,16 +4778,16 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0 'T_ICONS_PATH' => "{$web_path}{$config['icons_path']}/", 'T_RANKS_PATH' => "{$web_path}{$config['ranks_path']}/", 'T_UPLOAD_PATH' => "{$web_path}{$config['upload_path']}/", - 'T_STYLESHEET_LINK' => "{$web_path}styles/" . rawurlencode($user->theme['theme_path']) . '/theme/stylesheet.css', - 'T_STYLESHEET_LANG_LINK' => "{$web_path}styles/" . rawurlencode($user->theme['theme_path']) . '/theme/' . $user->lang_name . '/stylesheet.css', - 'T_STYLESHEET_NAME' => $user->theme['theme_name'], + 'T_STYLESHEET_LINK' => "{$web_path}styles/" . rawurlencode($user->theme['style_path']) . '/theme/stylesheet.css', + 'T_STYLESHEET_LANG_LINK' => "{$web_path}styles/" . rawurlencode($user->theme['style_path']) . '/theme/' . $user->lang_name . '/stylesheet.css', + 'T_STYLESHEET_NAME' => $user->theme['style_name'], 'T_JQUERY_LINK' => ($config['load_jquery_cdn'] && !empty($config['load_jquery_url'])) ? $config['load_jquery_url'] : "{$web_path}assets/javascript/jquery.js", 'S_JQUERY_FALLBACK' => ($config['load_jquery_cdn']) ? true : false, - 'T_THEME_NAME' => rawurlencode($user->theme['theme_path']), + 'T_THEME_NAME' => rawurlencode($user->theme['style_path']), 'T_THEME_LANG_NAME' => $user->data['user_lang'], - 'T_TEMPLATE_NAME' => $user->theme['template_path'], - 'T_SUPER_TEMPLATE_NAME' => rawurlencode((isset($user->theme['template_inherit_path']) && $user->theme['template_inherit_path']) ? $user->theme['template_inherit_path'] : $user->theme['template_path']), + 'T_TEMPLATE_NAME' => $user->theme['style_path'], + 'T_SUPER_TEMPLATE_NAME' => rawurlencode((isset($user->theme['style_parent_tree']) && $user->theme['style_parent_tree']) ? $user->theme['style_parent_tree'] : $user->theme['style_path']), 'T_IMAGES' => 'images', 'T_SMILIES' => $config['smilies_path'], 'T_AVATAR' => $config['avatar_path'], diff --git a/phpBB/includes/functions_messenger.php b/phpBB/includes/functions_messenger.php index f4e49b1b18..a5e7ad75ca 100644 --- a/phpBB/includes/functions_messenger.php +++ b/phpBB/includes/functions_messenger.php @@ -201,17 +201,16 @@ class messenger { // fall back to board default language if the user's language is // missing $template_file. If this does not exist either, - // $tpl->set_custom_template will do a trigger_error + // $tpl->set_filenames will do a trigger_error $template_lang = basename($config['default_lang']); } // tpl_msg now holds a template object we can use to parse the template file if (!isset($this->tpl_msg[$template_lang . $template_file])) { - $template_locator = new phpbb_template_locator(); - $template_path_provider = new phpbb_template_extension_path_provider($phpbb_extension_manager, new phpbb_template_path_provider()); - $this->tpl_msg[$template_lang . $template_file] = new phpbb_template($phpbb_root_path, $phpEx, $config, $user, $template_locator, $template_path_provider); - $tpl = &$this->tpl_msg[$template_lang . $template_file]; + $this->tpl_msg[$template_lang . $template_file] = new phpbb_style($phpbb_root_path, $phpEx, $config, $user, $phpbb_extension_manager); + $stl = &$this->tpl_msg[$template_lang . $template_file]; + $tpl = $stl->template; $fallback_template_path = false; @@ -229,7 +228,7 @@ class messenger } } - $tpl->set_custom_template($template_path, $template_lang . '_email', $fallback_template_path); + $stl->set_custom_style($template_lang . '_email', array($template_path, $fallback_template_path), ''); $tpl->set_filenames(array( 'body' => $template_file . '.txt', @@ -237,6 +236,7 @@ class messenger } $this->tpl_obj = &$this->tpl_msg[$template_lang . $template_file]; + $this->tpl_obj = $this->tpl_obj->template; $this->vars = &$this->tpl_obj->_rootref; $this->tpl_msg = ''; diff --git a/phpBB/includes/session.php b/phpBB/includes/session.php index 6dad068ecb..2fd2efe9b2 100644 --- a/phpBB/includes/session.php +++ b/phpBB/includes/session.php @@ -1568,9 +1568,9 @@ class user extends session /** * Setup basic user-specific items (style, language, ...) */ - function setup($lang_set = false, $style = false) + function setup($lang_set = false, $style_id = false) { - global $db, $template, $config, $auth, $phpEx, $phpbb_root_path, $cache; + global $db, $style, $template, $config, $auth, $phpEx, $phpbb_root_path, $cache; if ($this->data['user_id'] != ANONYMOUS) { @@ -1643,40 +1643,36 @@ class user extends session { global $SID, $_EXTRA_URL; - $style = $style_request; - $SID .= '&style=' . $style; - $_EXTRA_URL = array('style=' . $style); + $style_id = $style_request; + $SID .= '&style=' . $style_id; + $_EXTRA_URL = array('style=' . $style_id); } else { // Set up style - $style = ($style) ? $style : ((!$config['override_user_style']) ? $this->data['user_style'] : $config['default_style']); + $style_id = ($style_id) ? $style_id : ((!$config['override_user_style']) ? $this->data['user_style'] : $config['default_style']); } - $sql = 'SELECT s.style_id, t.template_path, t.template_id, t.bbcode_bitfield, t.template_inherits_id, t.template_inherit_path, c.theme_path, c.theme_name, c.theme_id - FROM ' . STYLES_TABLE . ' s, ' . STYLES_TEMPLATE_TABLE . ' t, ' . STYLES_THEME_TABLE . " c - WHERE s.style_id = $style - AND t.template_id = s.template_id - AND c.theme_id = s.theme_id"; + $sql = 'SELECT * + FROM ' . STYLES_TABLE . " s + WHERE s.style_id = $style_id"; $result = $db->sql_query($sql, 3600); $this->theme = $db->sql_fetchrow($result); $db->sql_freeresult($result); // User has wrong style - if (!$this->theme && $style == $this->data['user_style']) + if (!$this->theme && $style_id == $this->data['user_style']) { - $style = $this->data['user_style'] = $config['default_style']; + $style_id = $this->data['user_style'] = $config['default_style']; $sql = 'UPDATE ' . USERS_TABLE . " - SET user_style = $style + SET user_style = $style_id WHERE user_id = {$this->data['user_id']}"; $db->sql_query($sql); - $sql = 'SELECT s.style_id, t.template_path, t.template_id, t.bbcode_bitfield, c.theme_path, c.theme_name, c.theme_id - FROM ' . STYLES_TABLE . ' s, ' . STYLES_TEMPLATE_TABLE . ' t, ' . STYLES_THEME_TABLE . " c - WHERE s.style_id = $style - AND t.template_id = s.template_id - AND c.theme_id = s.theme_id"; + $sql = 'SELECT * + FROM ' . STYLES_TABLE . " s + WHERE s.style_id = $style_id"; $result = $db->sql_query($sql, 3600); $this->theme = $db->sql_fetchrow($result); $db->sql_freeresult($result); @@ -1708,7 +1704,7 @@ class user extends session } } - $template->set_template(); + $style->set_style(); $this->img_lang = $this->lang_name; diff --git a/phpBB/includes/style/extension_path_provider.php b/phpBB/includes/style/extension_path_provider.php new file mode 100644 index 0000000000..1fb6580ce1 --- /dev/null +++ b/phpBB/includes/style/extension_path_provider.php @@ -0,0 +1,125 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2011 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* Provides a style resource locator with core style paths and extension style paths +* +* Finds installed style paths and makes them available to the resource locator. +* +* @package phpBB3 +*/ +class phpbb_style_extension_path_provider extends phpbb_extension_provider implements phpbb_style_path_provider_interface +{ + /** + * Optional prefix for style paths searched within extensions. + * + * Empty by default. Relative to the extension directory. As an example, it + * could be adm/ for admin style. + * + * @var string + */ + protected $ext_dir_prefix = ''; + + /** + * A provider of paths to be searched for styles + * @var phpbb_style_path_provider + */ + protected $base_path_provider; + + /** + * Constructor stores extension manager + * + * @param phpbb_extension_manager $extension_manager phpBB extension manager + * @param phpbb_style_path_provider $base_path_provider A simple path provider + * to provide paths to be located in extensions + */ + public function __construct(phpbb_extension_manager $extension_manager, phpbb_style_path_provider $base_path_provider) + { + parent::__construct($extension_manager); + $this->base_path_provider = $base_path_provider; + } + + /** + * Sets a prefix for style paths searched within extensions. + * + * The prefix is inserted between the extension's path e.g. ext/foo/ and + * the looked up style path, e.g. styles/bar/. So it should not have a + * leading slash, but should have a trailing slash. + * + * @param string $ext_dir_prefix The prefix including trailing slash + * @return null + */ + public function set_ext_dir_prefix($ext_dir_prefix) + { + $this->ext_dir_prefix = $ext_dir_prefix; + } + + /** + * Finds style paths using the extension manager + * + * Locates a path (e.g. styles/prosilver/) in all active extensions. + * Then appends the core style paths based in the current working + * directory. + * + * @return array List of style paths + */ + public function find() + { + $directories = array(); + + $finder = $this->extension_manager->get_finder(); + foreach ($this->base_path_provider as $path) + { + if ($path && !phpbb_is_absolute($path)) + { + $directories = array_merge($directories, $finder + ->directory('/' . $this->ext_dir_prefix . $path) + ->get_directories() + ); + } + } + + foreach ($this->base_path_provider as $path) + { + $directories[] = $path; + } + + return $directories; + } + + /** + * Overwrites the current style paths + * + * @param array $styles An array of style paths. The first element is the main style. + * @return null + */ + public function set_styles(array $styles) + { + $this->base_path_provider->set_styles($styles); + $this->items = null; + } + + /** + * Retrieves the path to the main style passed into set_styles() + * + * @return string Main style path + */ + public function get_main_style_path() + { + return $this->base_path_provider->get_main_style_path(); + } +} diff --git a/phpBB/includes/style/path_provider.php b/phpBB/includes/style/path_provider.php new file mode 100644 index 0000000000..c229af92ba --- /dev/null +++ b/phpBB/includes/style/path_provider.php @@ -0,0 +1,74 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2011 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* Provides a style resource locator with paths +* +* Finds installed style paths and makes them available to the resource locator. +* +* @package phpBB3 +*/ +class phpbb_style_path_provider implements IteratorAggregate, phpbb_style_path_provider_interface +{ + protected $main_style_name = ''; + protected $paths = array(); + + /** + * Ignores the extension dir prefix + * + * @param string $ext_dir_prefix The prefix including trailing slash + * @return null + */ + public function set_ext_dir_prefix($ext_dir_prefix) + { + } + + /** + * Overwrites the current style paths + * + * The first element of the passed styles map, is considered the main + * style and can be retrieved through get_main_style_path(). + * + * @param array $styles An array of style paths. The first element is the main style. + * @return null + */ + public function set_styles(array $styles) + { + $this->paths = $styles; + $this->main_style_path = $this->paths[0]; + } + + /** + * Retrieves the path to the main style passed into set_styles() + * + * @return string Main style path + */ + public function get_main_style_path() + { + return $this->main_style_path; + } + + /** + * Retrieve an iterator over all style paths + * + * @return ArrayIterator An iterator for the array of style paths + */ + public function getIterator() + { + return new ArrayIterator($this->paths); + } +} diff --git a/phpBB/includes/style/path_provider_interface.php b/phpBB/includes/style/path_provider_interface.php new file mode 100644 index 0000000000..7ae94e17f4 --- /dev/null +++ b/phpBB/includes/style/path_provider_interface.php @@ -0,0 +1,49 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2011 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* Provides a style resource locator with paths +* +* Finds installed style paths and makes them available to the resource locator. +* +* @package phpBB3 +*/ +interface phpbb_style_path_provider_interface extends Traversable +{ + /** + * Defines a prefix to use for style paths in extensions + * + * @param string $ext_dir_prefix The prefix including trailing slash + * @return null + */ + public function set_ext_dir_prefix($ext_dir_prefix); + + /** + * Overwrites the current style paths + * + * @param array $styles An array of style paths. The first element is the main style. + * @return null + */ + public function set_styles(array $styles); + + /** + * Retrieves the path to the main style passed into set_styles() + * + * @return string Main style path + */ + public function get_main_style_path(); +} diff --git a/phpBB/includes/template/locator.php b/phpBB/includes/style/resource_locator.php index d4502d7984..af261534c3 100644 --- a/phpBB/includes/template/locator.php +++ b/phpBB/includes/style/resource_locator.php @@ -17,29 +17,42 @@ if (!defined('IN_PHPBB')) /** -* Template locator. Maintains mapping from template handles to source paths. +* Style resource locator. +* Maintains mapping from template handles to source template file paths. +* Locates style files: resources (such as .js and .css files) and templates. * -* Template locator is aware of template inheritance, and can return actual -* filesystem paths (i.e., the "primary" template or the "parent" template) +* Style resource locator is aware of styles tree, and can return actual +* filesystem paths (i.e., the "child" style or the "parent" styles) * depending on what files exist. * +* Root paths stored in locator are paths to style directories. Templates are +* stored in subdirectory that $template_path points to. +* * @package phpBB3 */ -class phpbb_template_locator +class phpbb_style_resource_locator { /** - * Paths to directories that templates are stored in. + * Paths to style directories. * @var array */ private $roots = array(); /** - * Index of the main template in the roots array + * Index of the main style in the roots array. * @var int */ private $main_root_id = 0; /** + * Location of templates directory within style directories. + * Must have trailing slash. Empty if templates are stored in root + * style directory, such as admin control panel templates. + * @var string + */ + public $template_path = 'template/'; + + /** * Map from root index to handles to source template file paths. * Normally it only contains paths for handles that are used * (or are likely to be used) by the page being rendered and not @@ -57,34 +70,34 @@ class phpbb_template_locator private $filenames = array(); /** - * Set main template location (must have been added through set_paths first). + * Set main style location (must have been added through set_paths first). * - * @param string $template_path Path to template directory + * @param string $style_path Path to style directory * @return null */ - public function set_main_template($template) + public function set_main_style($style_path) { - $this->main_root_id = array_search($template, $this->roots, true); + $this->main_root_id = array_search($style_path, $this->roots, true); } /** - * Sets the list of template paths + * Sets the list of style paths * - * These paths will be searched for template files in the provided order. + * These paths will be searched for style files in the provided order. * Paths may be outside of phpBB, but templates loaded from these paths * will still be cached. * - * @param array $template_paths An array of paths to template directories + * @param array $style_paths An array of paths to style directories * @return null */ - public function set_paths($template_paths) + public function set_paths($style_paths) { $this->roots = array(); $this->files = array(); $this->filenames = array(); $this->main_root_id = 0; - foreach ($template_paths as $path) + foreach ($style_paths as $path) { // Make sure $path has no ending slash if (substr($path, -1) === '/') @@ -107,14 +120,14 @@ class phpbb_template_locator { if (empty($filename)) { - trigger_error("template locator: set_filenames: Empty filename specified for $handle", E_USER_ERROR); + trigger_error("style resource locator: set_filenames: Empty filename specified for $handle", E_USER_ERROR); } $this->filename[$handle] = $filename; foreach ($this->roots as $root_index => $root) { - $this->files[$root_index][$handle] = $root . '/' . $filename; + $this->files[$root_index][$handle] = $root . '/' . $this->template_path . $filename; } } } @@ -133,37 +146,37 @@ class phpbb_template_locator { if (!isset($this->filename[$handle])) { - trigger_error("template locator: get_filename_for_handle: No file specified for handle $handle", E_USER_ERROR); + trigger_error("style resource locator: get_filename_for_handle: No file specified for handle $handle", E_USER_ERROR); } return $this->filename[$handle]; } /** * Determines the source file path for a template handle without - * regard for template inheritance. + * regard for styles tree. * - * This function returns the path in "primary" template directory + * This function returns the path in "primary" style directory * corresponding to the given template handle. That path may or * may not actually exist on the filesystem. Because this function * does not perform stat calls to determine whether the path it * returns actually exists, it is faster than get_source_file_for_handle. * * Use get_source_file_for_handle to obtain the actual path that is - * guaranteed to exist (which might come from the parent/fallback - * template directory if template inheritance is used). + * guaranteed to exist (which might come from the parent style + * directory if primary style has parent styles). * * This function will trigger an error if the handle was never * associated with a template file via set_filenames. * * @param $handle string Template handle - * @return string Path to source file path in primary template directory + * @return string Path to source file path in primary style directory */ public function get_virtual_source_file_for_handle($handle) { // If we don't have a file assigned to this handle, die. if (!isset($this->files[$this->main_root_id][$handle])) { - trigger_error("template locator: No file specified for handle $handle", E_USER_ERROR); + trigger_error("style resource locator: No file specified for handle $handle", E_USER_ERROR); } $source_file = $this->files[$this->main_root_id][$handle]; @@ -172,7 +185,7 @@ class phpbb_template_locator /** * Determines the source file path for a template handle, accounting - * for template inheritance and verifying that the path exists. + * for styles tree and verifying that the path exists. * * This function returns the actual path that may be compiled for * the specified template handle. It will trigger an error if @@ -181,7 +194,7 @@ class phpbb_template_locator * filesystem. * * Use get_virtual_source_file_for_handle to just resolve a template - * handle to a path without any filesystem or inheritance checks. + * handle to a path without any filesystem or styles tree checks. * * @param string $handle Template handle (i.e. "friendly" template name) * @return string Source file path @@ -191,7 +204,7 @@ class phpbb_template_locator // If we don't have a file assigned to this handle, die. if (!isset($this->files[$this->main_root_id][$handle])) { - trigger_error("template locator: No file specified for handle $handle", E_USER_ERROR); + trigger_error("style resource locator: No file specified for handle $handle", E_USER_ERROR); } // locate a source file that exists @@ -206,7 +219,7 @@ class phpbb_template_locator // search failed if (!file_exists($source_file)) { - trigger_error("template locator: File for handle $handle does not exist. Could not find: $tried", E_USER_ERROR); + trigger_error("style resource locator: File for handle $handle does not exist. Could not find: $tried", E_USER_ERROR); } return $source_file; diff --git a/phpBB/includes/style/style.php b/phpBB/includes/style/style.php new file mode 100644 index 0000000000..5dee0a138c --- /dev/null +++ b/phpBB/includes/style/style.php @@ -0,0 +1,154 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2005 phpBB Group, sections (c) 2001 ispi of Lincoln Inc +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* Base Style class. +* @package phpBB3 +*/ +class phpbb_style +{ + /** + * @var phpbb_style_template Template class. + * Handles everything related to templates. + */ + public $template; + + /** + * @var string phpBB root path + */ + private $phpbb_root_path; + + /** + * @var phpEx PHP file extension + */ + private $phpEx; + + /** + * @var phpbb_config phpBB config instance + */ + private $config; + + /** + * @var user current user + */ + private $user; + + /** + * Style resource locator + * @var phpbb_style_resource_locator + * This item is temporary public, until locate() function is implemented + */ + public $locator; + + /** + * Style path provider + * @var phpbb_style_path_provider + */ + private $provider; + + /** + * Constructor. + * + * @param string $phpbb_root_path phpBB root path + * @param user $user current user + * @param phpbb_extension_manager $phpbb_extension_manager extension manager. Set it to false if extension manager should not be used. + */ + public function __construct($phpbb_root_path, $phpEx, $config, $user, $phpbb_extension_manager = false) + { + $this->phpbb_root_path = $phpbb_root_path; + $this->phpEx = $phpEx; + $this->config = $config; + $this->user = $user; + $this->locator = new phpbb_style_resource_locator(); + $this->provider = new phpbb_style_path_provider(); + if ($phpbb_extension_manager !== false) + { + $this->provider = new phpbb_style_extension_path_provider($phpbb_extension_manager, $this->provider); + } + $this->template = new phpbb_style_template($this->phpbb_root_path, $this->phpEx, $this->config, $this->user, $this->locator, $this->provider); + } + + /** + * Set style location based on (current) user's chosen style. + */ + public function set_style() + { + $style_name = $this->user->theme['style_path']; + $style_dirs = ($this->user->theme['style_parent_id']) ? array_reverse(explode('/', $this->user->theme['style_parent_tree'])) : array(); + $paths = array($this->get_style_path($style_name)); + foreach ($style_dirs as $dir) + { + $paths[] = $this->get_style_path($dir); + } + + return $this->set_custom_style($style_name, $paths); + } + + /** + * Set custom style location (able to use directory outside of phpBB). + * + * Note: Templates are still compiled to phpBB's cache directory. + * + * @param string $name Name of style, used for cache prefix. Examples: "admin", "prosilver" + * @param array or string $paths Array of style paths, relative to current root directory + * @param string $template_path Path to templates, relative to style directory. False if path should not be changed. + */ + public function set_custom_style($name, $paths, $template_path = false) + { + if (is_string($paths)) + { + $paths = array($paths); + } + + $this->provider->set_styles($paths); + $this->locator->set_paths($this->provider); + $this->locator->set_main_style($this->provider->get_main_style_path()); + + $this->template->cachepath = $this->phpbb_root_path . 'cache/tpl_' . str_replace('_', '-', $name) . '_'; + + $this->template->context = new phpbb_style_template_context(); + + if ($template_path !== false) + { + $this->template->template_path = $this->locator->template_path = $template_path; + } + + return true; + } + + /** + * Get location of style directory for specific style_path + * + * @param string $path Style path, such as "prosilver" + * @return string Path to style directory, relative to current path + */ + public function get_style_path($path) + { + return $this->phpbb_root_path . 'styles/' . $path; + } + + /** + * Defines a prefix to use for style paths in extensions + * + * @param string $ext_dir_prefix The prefix including trailing slash + * @return null + */ + public function set_ext_dir_prefix($ext_dir_prefix) + { + $this->provider->set_ext_dir_prefix($ext_dir_prefix); + } +} diff --git a/phpBB/includes/template/template.php b/phpBB/includes/style/template.php index bac5445511..21a2e821dd 100644 --- a/phpBB/includes/template/template.php +++ b/phpBB/includes/style/template.php @@ -29,13 +29,13 @@ if (!defined('IN_PHPBB')) * Base Template class. * @package phpBB3 */ -class phpbb_template +class phpbb_style_template { /** - * @var phpbb_template_context Template context. + * @var phpbb_style_template_context Template context. * Stores template data used during template rendering. */ - private $context; + public $context; /** * @var string Path of the cache directory for the template @@ -63,88 +63,43 @@ class phpbb_template private $user; /** - * Template locator - * @var phpbb_template_locator + * Style resource locator + * @var phpbb_style_resource_locator */ private $locator; /** * Template path provider - * @var phpbb_template_path_provider + * @var phpbb_style_path_provider */ private $provider; /** + * Location of templates directory within style directories + * @var string + */ + public $template_path = 'template/'; + + /** * Constructor. * * @param string $phpbb_root_path phpBB root path * @param user $user current user - * @param phpbb_template_locator $locator template locator - * @param phpbb_template_path_provider $provider template path provider + * @param phpbb_style_resource_locator $locator style resource locator + * @param phpbb_style_path_provider $provider style path provider */ - public function __construct($phpbb_root_path, $phpEx, $config, $user, phpbb_template_locator $locator, phpbb_template_path_provider_interface $provider) + public function __construct($phpbb_root_path, $phpEx, $config, $user, phpbb_style_resource_locator $locator, phpbb_style_path_provider_interface $provider) { $this->phpbb_root_path = $phpbb_root_path; $this->phpEx = $phpEx; $this->config = $config; $this->user = $user; $this->locator = $locator; + $this->template_path = $this->locator->template_path; $this->provider = $provider; } /** - * Set template location based on (current) user's chosen style. - */ - public function set_template() - { - $template_name = $this->user->theme['template_path']; - $fallback_name = ($this->user->theme['template_inherits_id']) ? $this->user->theme['template_inherit_path'] : false; - - return $this->set_custom_template(false, $template_name, false, $fallback_name); - } - - /** - * Defines a prefix to use for template paths in extensions - * - * @param string $ext_dir_prefix The prefix including trailing slash - * @return null - */ - public function set_ext_dir_prefix($ext_dir_prefix) - { - $this->provider->set_ext_dir_prefix($ext_dir_prefix); - } - - /** - * Set custom template location (able to use directory outside of phpBB). - * - * Note: Templates are still compiled to phpBB's cache directory. - * - * @param string $template_path Path to template directory - * @param string $template_name Name of template - * @param string $fallback_template_path Path to fallback template - * @param string $fallback_template_name Name of fallback template - */ - public function set_custom_template($template_path, $template_name, $fallback_template_path = false, $fallback_template_name = false) - { - $templates = array($template_name => $template_path); - - if ($fallback_template_name !== false) - { - $templates[$fallback_template_name] = $fallback_template_path; - } - - $this->provider->set_templates($templates, $this->phpbb_root_path); - $this->locator->set_paths($this->provider); - $this->locator->set_main_template($this->provider->get_main_template_path()); - - $this->cachepath = $this->phpbb_root_path . 'cache/tpl_' . str_replace('_', '-', $template_name) . '_'; - - $this->context = new phpbb_template_context(); - - return true; - } - - /** * Sets the template filenames for handles. * * @param array $filname_array Should be a hash of handle => filename pairs. @@ -298,15 +253,15 @@ class phpbb_template * configuration setting may be used to force templates to be always * recompiled. * - * Returns an object implementing phpbb_template_renderer, or null + * Returns an object implementing phpbb_style_template_renderer, or null * if template loading or compilation failed. Call render() on the * renderer to display the template. This will result in template * contents sent to the output stream (unless, of course, output * buffering is in effect). * * @param string $handle Handle of the template to load - * @return phpbb_template_renderer Template renderer object, or null on failure - * @uses phpbb_template_compile is used to compile template source + * @return phpbb_style_template_renderer Template renderer object, or null on failure + * @uses phpbb_style_template_compile is used to compile template source */ private function _tpl_load($handle) { @@ -330,18 +285,18 @@ class phpbb_template // Recompile page if the original template is newer, otherwise load the compiled version if (!$recompile) { - return new phpbb_template_renderer_include($output_file, $this); + return new phpbb_style_template_renderer_include($output_file, $this); } - $compile = new phpbb_template_compile($this->config['tpl_allow_php']); + $compile = new phpbb_style_template_compile($this->config['tpl_allow_php']); if ($compile->compile_file_to_file($source_file, $output_file) !== false) { - $renderer = new phpbb_template_renderer_include($output_file, $this); + $renderer = new phpbb_style_template_renderer_include($output_file, $this); } else if (($code = $compile->compile_file($source_file)) !== false) { - $renderer = new phpbb_template_renderer_eval($code, $this); + $renderer = new phpbb_style_template_renderer_eval($code, $this); } else { @@ -403,7 +358,7 @@ class phpbb_template $this->context->append_var($varname, $varval); } - // Docstring is copied from phpbb_template_context method with the same name. + // Docstring is copied from phpbb_style_template_context method with the same name. /** * Assign key variable pairs from an array to a specified block * @param string $blockname Name of block to assign $vararray to @@ -414,7 +369,7 @@ class phpbb_template return $this->context->assign_block_vars($blockname, $vararray); } - // Docstring is copied from phpbb_template_context method with the same name. + // Docstring is copied from phpbb_style_template_context method with the same name. /** * Change already assigned key variable pair (one-dimensional - single loop entry) * diff --git a/phpBB/includes/template/compile.php b/phpBB/includes/style/template_compile.php index b0009421c5..3ef3fffc00 100644 --- a/phpBB/includes/template/compile.php +++ b/phpBB/includes/style/template_compile.php @@ -15,7 +15,7 @@ if (!defined('IN_PHPBB')) exit; } -stream_filter_register('phpbb_template', 'phpbb_template_filter'); +stream_filter_register('phpbb_template', 'phpbb_style_template_filter'); /** * Extension of template class - Functions needed for compiling templates only. @@ -23,7 +23,7 @@ stream_filter_register('phpbb_template', 'phpbb_template_filter'); * @package phpBB3 * @uses template_filter As a PHP stream filter to perform compilation of templates */ -class phpbb_template_compile +class phpbb_style_template_compile { /** * Whether <!-- PHP --> tags are allowed diff --git a/phpBB/includes/template/context.php b/phpBB/includes/style/template_context.php index ec09da1cf3..b22f77da2e 100644 --- a/phpBB/includes/template/context.php +++ b/phpBB/includes/style/template_context.php @@ -20,7 +20,7 @@ if (!defined('IN_PHPBB')) * * @package phpBB3 */ -class phpbb_template_context +class phpbb_style_template_context { /** * variable that holds all the data we'll be substituting into @@ -86,7 +86,7 @@ class phpbb_template_context * Returns a reference to template data array. * * This function is public so that template renderer may invoke it. - * Users should alter template variables via functions in phpbb_template. + * Users should alter template variables via functions in phpbb_style_template. * * Note: modifying returned array will affect data stored in the context. * diff --git a/phpBB/includes/template/filter.php b/phpBB/includes/style/template_filter.php index f55c8d7e9c..04fe85e07f 100644 --- a/phpBB/includes/template/filter.php +++ b/phpBB/includes/style/template_filter.php @@ -35,7 +35,7 @@ if (!defined('IN_PHPBB')) * @see template_compile * @package phpBB3 */ -class phpbb_template_filter extends php_user_filter +class phpbb_style_template_filter extends php_user_filter { const REGEX_NS = '[a-z_][a-z_0-9]+'; diff --git a/phpBB/includes/template/renderer.php b/phpBB/includes/style/template_renderer.php index 30e234a733..bd2a786e86 100644 --- a/phpBB/includes/template/renderer.php +++ b/phpBB/includes/style/template_renderer.php @@ -23,12 +23,12 @@ if (!defined('IN_PHPBB')) * * @package phpBB3 */ -interface phpbb_template_renderer +interface phpbb_style_template_renderer { /** * Displays the template managed by this renderer. * - * @param phpbb_template_context $context Template context to use + * @param phpbb_style_template_context $context Template context to use * @param array $lang Language entries to use */ public function render($context, $lang); diff --git a/phpBB/includes/template/renderer_eval.php b/phpBB/includes/style/template_renderer_eval.php index f8e4cb7b10..3e08b06e69 100644 --- a/phpBB/includes/template/renderer_eval.php +++ b/phpBB/includes/style/template_renderer_eval.php @@ -21,7 +21,7 @@ if (!defined('IN_PHPBB')) * * @package phpBB3 */ -class phpbb_template_renderer_eval implements phpbb_template_renderer +class phpbb_style_template_renderer_eval implements phpbb_style_template_renderer { /** * Template code to be eval'ed. @@ -33,7 +33,7 @@ class phpbb_template_renderer_eval implements phpbb_template_renderer * Template includes are delegated to template object $template. * * @param string $code php code of the template - * @param phpbb_template $template template object + * @param phpbb_style_template $template template object */ public function __construct($code, $template) { @@ -45,7 +45,7 @@ class phpbb_template_renderer_eval implements phpbb_template_renderer * Displays the template managed by this renderer by eval'ing php code * of the template. * - * @param phpbb_template_context $context Template context to use + * @param phpbb_style_template_context $context Template context to use * @param array $lang Language entries to use */ public function render($context, $lang) diff --git a/phpBB/includes/template/renderer_include.php b/phpBB/includes/style/template_renderer_include.php index f5c9026abf..91c1a1bb65 100644 --- a/phpBB/includes/template/renderer_include.php +++ b/phpBB/includes/style/template_renderer_include.php @@ -22,7 +22,7 @@ if (!defined('IN_PHPBB')) * * @package phpBB3 */ -class phpbb_template_renderer_include implements phpbb_template_renderer +class phpbb_style_template_renderer_include implements phpbb_style_template_renderer { /** * Template path to be included. @@ -45,7 +45,7 @@ class phpbb_template_renderer_include implements phpbb_template_renderer * Displays the template managed by this renderer by including * the php file containing the template. * - * @param phpbb_template_context $context Template context to use + * @param phpbb_style_template_context $context Template context to use * @param array $lang Language entries to use */ public function render($context, $lang) diff --git a/phpBB/includes/template/extension_path_provider.php b/phpBB/includes/template/extension_path_provider.php deleted file mode 100644 index 2897f60ac1..0000000000 --- a/phpBB/includes/template/extension_path_provider.php +++ /dev/null @@ -1,130 +0,0 @@ -<?php -/** -* -* @package phpBB3 -* @copyright (c) 2011 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* Provides a template locator with core template paths and extension template paths -* -* Finds installed template paths and makes them available to the locator. -* -* @package phpBB3 -*/ -class phpbb_template_extension_path_provider extends phpbb_extension_provider implements phpbb_template_path_provider_interface -{ - /** - * Optional prefix for template paths searched within extensions. - * - * Empty by default. Relative to the extension directory. As an example, it - * could be adm/ for admin templates. - * - * @var string - */ - protected $ext_dir_prefix = ''; - - /** - * A provider of paths to be searched for templates - * @var phpbb_template_path_provider - */ - protected $base_path_provider; - - /** - * Constructor stores extension manager - * - * @param phpbb_extension_manager $extension_manager phpBB extension manager - * @param phpbb_template_path_provider $base_path_provider A simple path provider - * to provide paths to be located in extensions - */ - public function __construct(phpbb_extension_manager $extension_manager, phpbb_template_path_provider $base_path_provider) - { - parent::__construct($extension_manager); - $this->base_path_provider = $base_path_provider; - } - - /** - * Sets a prefix for template paths searched within extensions. - * - * The prefix is inserted between the extension's path e.g. ext/foo/ and - * the looked up template path, e.g. styles/bar/template/some.html. So it - * should not have a leading slash, but should have a trailing slash. - * - * @param string $ext_dir_prefix The prefix including trailing slash - * @return null - */ - public function set_ext_dir_prefix($ext_dir_prefix) - { - $this->ext_dir_prefix = $ext_dir_prefix; - } - - /** - * Finds template paths using the extension manager - * - * Locates a path (e.g. styles/prosilver/template/) in all active extensions. - * Then appends the core template paths based in the current working - * directory. - * - * @return array List of template paths - */ - public function find() - { - $directories = array(); - - $finder = $this->extension_manager->get_finder(); - foreach ($this->base_path_provider as $path) - { - if ($path && !phpbb_is_absolute($path)) - { - $directories = array_merge($directories, $finder - ->directory('/' . $this->ext_dir_prefix . $path) - ->get_directories() - ); - } - } - - foreach ($this->base_path_provider as $path) - { - $directories[] = $path; - } - - return $directories; - } - - /** - * Overwrites the current template names and paths - * - * @param array $templates An associative map from template names to paths. - * The first element is the main template. - * If the path is false, it will be generated from - * the supplied name. - * @param string $style_root_path The root directory for styles identified - * by name only. - * @return null - */ - public function set_templates(array $templates, $style_root_path) - { - $this->base_path_provider->set_templates($templates, $style_root_path); - $this->items = null; - } - - /** - * Retrieves the path to the main template passed into set_templates() - * - * @return string Main template path - */ - public function get_main_template_path() - { - return $this->base_path_provider->get_main_template_path(); - } -} diff --git a/phpBB/includes/template/path_provider.php b/phpBB/includes/template/path_provider.php deleted file mode 100644 index b0b545973d..0000000000 --- a/phpBB/includes/template/path_provider.php +++ /dev/null @@ -1,102 +0,0 @@ -<?php -/** -* -* @package phpBB3 -* @copyright (c) 2011 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* Provides a template locator with paths -* -* Finds installed template paths and makes them available to the locator. -* -* @package phpBB3 -*/ -class phpbb_template_path_provider implements IteratorAggregate, phpbb_template_path_provider_interface -{ - protected $main_template_name = ''; - protected $paths = array(); - - /** - * Ignores the extension dir prefix - * - * @param string $ext_dir_prefix The prefix including trailing slash - * @return null - */ - public function set_ext_dir_prefix($ext_dir_prefix) - { - } - - /** - * Overwrites the current template names and paths - * - * The first element of the passed templates map, is considered the main - * template and can be retrieved through get_main_template_path(). - * - * @param array $templates An associative map from template names to paths. - * The first element is the main template. - * If the path is false, it will be generated from - * the supplied name. - * @param string $style_root_path The root directory for styles identified - * by name only. - * @return null - */ - public function set_templates(array $templates, $style_root_path) - { - $this->paths = array(); - - foreach ($templates as $name => $path) - { - if (!$path) - { - $path = $style_root_path . $this->template_root_for_style($name); - } - - $this->paths[] = $path; - } - - $this->main_template_path = $this->paths[0]; - } - - /** - * Retrieves the path to the main template passed into set_templates() - * - * @return string Main template path - */ - public function get_main_template_path() - { - return $this->main_template_path; - } - - /** - * Converts a style name to relative (to board root or extension) path to - * the style's template files. - * - * @param $style_name string Style name - * @return string Path to style template files - */ - private function template_root_for_style($style_name) - { - return 'styles/' . $style_name . '/template'; - } - - /** - * Retrieve an iterator over all template paths - * - * @return ArrayIterator An iterator for the array of template paths - */ - public function getIterator() - { - return new ArrayIterator($this->paths); - } -} diff --git a/phpBB/includes/template/path_provider_interface.php b/phpBB/includes/template/path_provider_interface.php deleted file mode 100644 index 8b3a406d2a..0000000000 --- a/phpBB/includes/template/path_provider_interface.php +++ /dev/null @@ -1,54 +0,0 @@ -<?php -/** -* -* @package phpBB3 -* @copyright (c) 2011 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* Provides a template locator with paths -* -* Finds installed template paths and makes them available to the locator. -* -* @package phpBB3 -*/ -interface phpbb_template_path_provider_interface extends Traversable -{ - /** - * Defines a prefix to use for template paths in extensions - * - * @param string $ext_dir_prefix The prefix including trailing slash - * @return null - */ - public function set_ext_dir_prefix($ext_dir_prefix); - - /** - * Overwrites the current template names and paths - * - * @param array $templates An associative map from template names to paths. - * The first element is the main template. - * If the path is false, it will be generated from - * the supplied name. - * @param string $style_root_path The root directory for styles identified - * by name only. - * @return null - */ - public function set_templates(array $templates, $style_root_path); - - /** - * Retrieves the path to the main template passed into set_templates() - * - * @return string Main template path - */ - public function get_main_template_path(); -} diff --git a/phpBB/install/database_update.php b/phpBB/install/database_update.php index 25b6387485..18ca4870fb 100644 --- a/phpBB/install/database_update.php +++ b/phpBB/install/database_update.php @@ -1089,6 +1089,12 @@ function database_update_info() PROFILE_FIELDS_TABLE => array( 'field_show_on_pm' => array('BOOL', 0), ), + STYLES_TABLE => array( + 'style_path' => array('VCHAR:100', ''), + 'bbcode_bitfield' => array('VCHAR:255', 'kNg='), + 'style_parent_id' => array('UINT:4', 0), + 'style_parent_tree' => array('TEXT', ''), + ), REPORTS_TABLE => array( 'reported_post_text' => array('MTEXT_UNI', ''), ), @@ -1101,20 +1107,16 @@ function database_update_info() 'drop_columns' => array( STYLES_TABLE => array( 'imageset_id', + 'template_id', + 'theme_id', ), - STYLES_TEMPLATE_TABLE => array( - 'template_storedb', - ), - STYLES_THEME_TABLE => array( - 'theme_storedb', - 'theme_mtime', - 'theme_data', - ), ), 'drop_tables' => array( STYLES_IMAGESET_TABLE, STYLES_IMAGESET_DATA_TABLE, + STYLES_TEMPLATE_TABLE, STYLES_TEMPLATE_DATA_TABLE, + STYLES_THEME_TABLE, ), ), ); @@ -2271,12 +2273,33 @@ function change_database_data(&$no_updates, $version) 'auth' => 'acl_a_attach', 'cat' => 'ACP_ATTACHMENTS', ), + 'install' => array( + 'base' => 'acp_styles' + 'class' => 'acp', + 'title' => 'ACP_STYLES_INSTALL', + 'auth' => 'acl_a_styles', + 'cat' => 'ACP_STYLE_MANAGEMENT', + ), + 'edit' => array( + 'base' => 'acp_styles' + 'class' => 'acp', + 'title' => 'ACP_STYLES_EDIT', + 'auth' => 'acl_a_styles', + 'cat' => 'ACP_STYLE_MANAGEMENT', + ), + 'cache' => array( + 'base' => 'acp_styles' + 'class' => 'acp', + 'title' => 'ACP_STYLES_CACHE', + 'auth' => 'acl_a_styles', + 'cat' => 'ACP_STYLE_MANAGEMENT', + ), ); _add_modules($modules_to_install); $sql = 'DELETE FROM ' . MODULES_TABLE . " - WHERE module_basename = 'styles' AND module_mode = 'imageset'"; + WHERE (module_basename = 'styles' OR module_basename = 'acp_styles') AND (module_mode = 'imageset' OR module_mode = 'theme' OR module_mode = 'template')"; _sql($sql, $errored, $error_ary); // Localise Global Announcements @@ -2366,7 +2389,13 @@ function change_database_data(&$no_updates, $version) { set_config('teampage_memberships', '1'); } + + // Clear styles table and add prosilver entry + _sql('DELETE FROM ' . STYLES_TABLE, $errored, $error_ary); + $sql = 'INSERT INTO ' . STYLES_TABLE . " (style_name, style_copyright, style_active, style_path, bbcode_bitfield, style_parent_id, style_parent_tree) VALUES ('prosilver', '© phpBB Group', 1, 'prosilver', 'kNg=', 0, '')"; + _sql($sql, $errored, $error_ary); + $no_updates = false; break; diff --git a/phpBB/install/index.php b/phpBB/install/index.php index a196a429e4..49f7847489 100644 --- a/phpBB/install/index.php +++ b/phpBB/install/index.php @@ -202,11 +202,10 @@ $config = new phpbb_config(array( 'load_tplcompile' => '1' )); -$phpbb_template_locator = new phpbb_template_locator(); -$phpbb_template_path_provider = new phpbb_template_path_provider(); -$template = new phpbb_template($phpbb_root_path, $phpEx, $config, $user, $phpbb_template_locator, $phpbb_template_path_provider); -$template->set_ext_dir_prefix('adm/'); -$template->set_custom_template('../adm/style', 'admin'); +$style = new phpbb_style($phpbb_root_path, $phpEx, $config, $user, false); +$style->set_ext_dir_prefix('adm/'); +$style->set_custom_style('admin', '../adm/style', ''); +$template = $style->template; $template->assign_var('T_ASSETS_PATH', '../assets'); $template->assign_var('T_TEMPLATE_PATH', '../adm/style'); diff --git a/phpBB/install/install_update.php b/phpBB/install/install_update.php index 9f50a56595..dcf01e5cc8 100644 --- a/phpBB/install/install_update.php +++ b/phpBB/install/install_update.php @@ -71,7 +71,7 @@ class install_update extends module function main($mode, $sub) { - global $template, $phpEx, $phpbb_root_path, $user, $db, $config, $cache, $auth, $language; + global $style, $template, $phpEx, $phpbb_root_path, $user, $db, $config, $cache, $auth, $language; global $request; $this->tpl_name = 'install_update'; @@ -131,7 +131,7 @@ class install_update extends module } // Set custom template again. ;) - $template->set_custom_template('../adm/style', 'admin'); + $style->set_custom_style('admin', '../adm/style', ''); $template->assign_vars(array( 'S_USER_LANG' => $user->lang['USER_LANG'], @@ -504,56 +504,6 @@ class install_update extends module // Add database update to log add_log('admin', 'LOG_UPDATE_PHPBB', $this->current_version, $this->update_to_version); - // Refresh prosilver css data - this may cause some unhappy users, but - $sql = 'SELECT * - FROM ' . STYLES_THEME_TABLE . " - WHERE LOWER(theme_name) = 'prosilver'"; - $result = $db->sql_query($sql); - $theme = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - if ($theme) - { - $recache = (empty($theme['theme_data'])) ? true : false; - $update_time = time(); - - // We test for stylesheet.css because it is faster and most likely the only file changed on common themes - if (!$recache && $theme['theme_mtime'] < @filemtime("{$phpbb_root_path}styles/" . $theme['theme_path'] . '/theme/stylesheet.css')) - { - $recache = true; - $update_time = @filemtime("{$phpbb_root_path}styles/" . $theme['theme_path'] . '/theme/stylesheet.css'); - } - else if (!$recache) - { - $last_change = $theme['theme_mtime']; - $dir = @opendir("{$phpbb_root_path}styles/{$theme['theme_path']}/theme"); - - if ($dir) - { - while (($entry = readdir($dir)) !== false) - { - if (substr(strrchr($entry, '.'), 1) == 'css' && $last_change < @filemtime("{$phpbb_root_path}styles/{$theme['theme_path']}/theme/{$entry}")) - { - $recache = true; - break; - } - } - closedir($dir); - } - } - - if ($recache) - { - // Instead of re-caching here, we simply remove theme_data... HAR HAR HAR (think about a carribean pirate) - $sql = 'UPDATE ' . STYLES_THEME_TABLE . " SET theme_data = '' - WHERE theme_id = " . $theme['theme_id']; - $db->sql_query($sql); - - $cache->destroy('sql', STYLES_THEME_TABLE); - $cache->destroy('sql', STYLES_TABLE); - } - } - $db->sql_return_on_error(true); $db->sql_query('DELETE FROM ' . CONFIG_TABLE . " WHERE config_name = 'version_update_from'"); $db->sql_return_on_error(false); @@ -1694,9 +1644,9 @@ class install_update extends module $info['custom'] = array(); /* // Get custom installed styles... - $sql = 'SELECT template_name, template_path - FROM ' . STYLES_TEMPLATE_TABLE . " - WHERE LOWER(template_name) NOT IN ('subsilver2', 'prosilver')"; + $sql = 'SELECT style_name, style_path + FROM ' . STYLES_TABLE . " + WHERE LOWER(style_name) NOT IN ('subsilver2', 'prosilver')"; $result = $db->sql_query($sql); $templates = array(); @@ -1715,7 +1665,7 @@ class install_update extends module { foreach ($templates as $row) { - $info['custom'][$filename][] = str_replace('/prosilver/', '/' . $row['template_path'] . '/', $filename); + $info['custom'][$filename][] = str_replace('/prosilver/', '/' . $row['style_path'] . '/', $filename); } } } diff --git a/phpBB/install/schemas/firebird_schema.sql b/phpBB/install/schemas/firebird_schema.sql index b88ed0a64a..51565ef2d4 100644 --- a/phpBB/install/schemas/firebird_schema.sql +++ b/phpBB/install/schemas/firebird_schema.sql @@ -1087,15 +1087,15 @@ CREATE TABLE phpbb_styles ( style_name VARCHAR(255) CHARACTER SET UTF8 DEFAULT '' NOT NULL COLLATE UNICODE, style_copyright VARCHAR(255) CHARACTER SET UTF8 DEFAULT '' NOT NULL COLLATE UNICODE, style_active INTEGER DEFAULT 1 NOT NULL, - template_id INTEGER DEFAULT 0 NOT NULL, - theme_id INTEGER DEFAULT 0 NOT NULL + style_path VARCHAR(100) CHARACTER SET NONE DEFAULT '' NOT NULL, + bbcode_bitfield VARCHAR(255) CHARACTER SET NONE DEFAULT 'kNg=' NOT NULL, + style_parent_id INTEGER DEFAULT 0 NOT NULL, + style_parent_tree BLOB SUB_TYPE TEXT CHARACTER SET NONE DEFAULT '' NOT NULL );; ALTER TABLE phpbb_styles ADD PRIMARY KEY (style_id);; CREATE UNIQUE INDEX phpbb_styles_style_name ON phpbb_styles(style_name);; -CREATE INDEX phpbb_styles_template_id ON phpbb_styles(template_id);; -CREATE INDEX phpbb_styles_theme_id ON phpbb_styles(theme_id);; CREATE GENERATOR phpbb_styles_gen;; SET GENERATOR phpbb_styles_gen TO 0;; @@ -1108,55 +1108,6 @@ BEGIN END;; -# Table: 'phpbb_styles_template' -CREATE TABLE phpbb_styles_template ( - template_id INTEGER NOT NULL, - template_name VARCHAR(255) CHARACTER SET UTF8 DEFAULT '' NOT NULL COLLATE UNICODE, - template_copyright VARCHAR(255) CHARACTER SET UTF8 DEFAULT '' NOT NULL COLLATE UNICODE, - template_path VARCHAR(100) CHARACTER SET NONE DEFAULT '' NOT NULL, - bbcode_bitfield VARCHAR(255) CHARACTER SET NONE DEFAULT 'kNg=' NOT NULL, - template_inherits_id INTEGER DEFAULT 0 NOT NULL, - template_inherit_path VARCHAR(255) CHARACTER SET NONE DEFAULT '' NOT NULL -);; - -ALTER TABLE phpbb_styles_template ADD PRIMARY KEY (template_id);; - -CREATE UNIQUE INDEX phpbb_styles_template_tmplte_nm ON phpbb_styles_template(template_name);; - -CREATE GENERATOR phpbb_styles_template_gen;; -SET GENERATOR phpbb_styles_template_gen TO 0;; - -CREATE TRIGGER t_phpbb_styles_template FOR phpbb_styles_template -BEFORE INSERT -AS -BEGIN - NEW.template_id = GEN_ID(phpbb_styles_template_gen, 1); -END;; - - -# Table: 'phpbb_styles_theme' -CREATE TABLE phpbb_styles_theme ( - theme_id INTEGER NOT NULL, - theme_name VARCHAR(255) CHARACTER SET UTF8 DEFAULT '' NOT NULL COLLATE UNICODE, - theme_copyright VARCHAR(255) CHARACTER SET UTF8 DEFAULT '' NOT NULL COLLATE UNICODE, - theme_path VARCHAR(100) CHARACTER SET NONE DEFAULT '' NOT NULL -);; - -ALTER TABLE phpbb_styles_theme ADD PRIMARY KEY (theme_id);; - -CREATE UNIQUE INDEX phpbb_styles_theme_theme_name ON phpbb_styles_theme(theme_name);; - -CREATE GENERATOR phpbb_styles_theme_gen;; -SET GENERATOR phpbb_styles_theme_gen TO 0;; - -CREATE TRIGGER t_phpbb_styles_theme FOR phpbb_styles_theme -BEFORE INSERT -AS -BEGIN - NEW.theme_id = GEN_ID(phpbb_styles_theme_gen, 1); -END;; - - # Table: 'phpbb_topics' CREATE TABLE phpbb_topics ( topic_id INTEGER NOT NULL, diff --git a/phpBB/install/schemas/mssql_schema.sql b/phpBB/install/schemas/mssql_schema.sql index a0399756e9..2c78dd009f 100644 --- a/phpBB/install/schemas/mssql_schema.sql +++ b/phpBB/install/schemas/mssql_schema.sql @@ -1323,8 +1323,10 @@ CREATE TABLE [phpbb_styles] ( [style_name] [varchar] (255) DEFAULT ('') NOT NULL , [style_copyright] [varchar] (255) DEFAULT ('') NOT NULL , [style_active] [int] DEFAULT (1) NOT NULL , - [template_id] [int] DEFAULT (0) NOT NULL , - [theme_id] [int] DEFAULT (0) NOT NULL + [style_path] [varchar] (100) DEFAULT ('') NOT NULL , + [bbcode_bitfield] [varchar] (255) DEFAULT ('kNg=') NOT NULL , + [style_parent_id] [int] DEFAULT (0) NOT NULL , + [style_parent_tree] [varchar] (8000) DEFAULT ('') NOT NULL ) ON [PRIMARY] GO @@ -1338,59 +1340,6 @@ GO CREATE UNIQUE INDEX [style_name] ON [phpbb_styles]([style_name]) ON [PRIMARY] GO -CREATE INDEX [template_id] ON [phpbb_styles]([template_id]) ON [PRIMARY] -GO - -CREATE INDEX [theme_id] ON [phpbb_styles]([theme_id]) ON [PRIMARY] -GO - - -/* - Table: 'phpbb_styles_template' -*/ -CREATE TABLE [phpbb_styles_template] ( - [template_id] [int] IDENTITY (1, 1) NOT NULL , - [template_name] [varchar] (255) DEFAULT ('') NOT NULL , - [template_copyright] [varchar] (255) DEFAULT ('') NOT NULL , - [template_path] [varchar] (100) DEFAULT ('') NOT NULL , - [bbcode_bitfield] [varchar] (255) DEFAULT ('kNg=') NOT NULL , - [template_inherits_id] [int] DEFAULT (0) NOT NULL , - [template_inherit_path] [varchar] (255) DEFAULT ('') NOT NULL -) ON [PRIMARY] -GO - -ALTER TABLE [phpbb_styles_template] WITH NOCHECK ADD - CONSTRAINT [PK_phpbb_styles_template] PRIMARY KEY CLUSTERED - ( - [template_id] - ) ON [PRIMARY] -GO - -CREATE UNIQUE INDEX [tmplte_nm] ON [phpbb_styles_template]([template_name]) ON [PRIMARY] -GO - - -/* - Table: 'phpbb_styles_theme' -*/ -CREATE TABLE [phpbb_styles_theme] ( - [theme_id] [int] IDENTITY (1, 1) NOT NULL , - [theme_name] [varchar] (255) DEFAULT ('') NOT NULL , - [theme_copyright] [varchar] (255) DEFAULT ('') NOT NULL , - [theme_path] [varchar] (100) DEFAULT ('') NOT NULL -) ON [PRIMARY] -GO - -ALTER TABLE [phpbb_styles_theme] WITH NOCHECK ADD - CONSTRAINT [PK_phpbb_styles_theme] PRIMARY KEY CLUSTERED - ( - [theme_id] - ) ON [PRIMARY] -GO - -CREATE UNIQUE INDEX [theme_name] ON [phpbb_styles_theme]([theme_name]) ON [PRIMARY] -GO - /* Table: 'phpbb_topics' diff --git a/phpBB/install/schemas/mysql_40_schema.sql b/phpBB/install/schemas/mysql_40_schema.sql index 69648c6b14..d19f1930d0 100644 --- a/phpBB/install/schemas/mysql_40_schema.sql +++ b/phpBB/install/schemas/mysql_40_schema.sql @@ -761,37 +761,12 @@ CREATE TABLE phpbb_styles ( style_name blob NOT NULL, style_copyright blob NOT NULL, style_active tinyint(1) UNSIGNED DEFAULT '1' NOT NULL, - template_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, - theme_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, - PRIMARY KEY (style_id), - UNIQUE style_name (style_name(255)), - KEY template_id (template_id), - KEY theme_id (theme_id) -); - - -# Table: 'phpbb_styles_template' -CREATE TABLE phpbb_styles_template ( - template_id mediumint(8) UNSIGNED NOT NULL auto_increment, - template_name blob NOT NULL, - template_copyright blob NOT NULL, - template_path varbinary(100) DEFAULT '' NOT NULL, + style_path varbinary(100) DEFAULT '' NOT NULL, bbcode_bitfield varbinary(255) DEFAULT 'kNg=' NOT NULL, - template_inherits_id int(4) UNSIGNED DEFAULT '0' NOT NULL, - template_inherit_path varbinary(255) DEFAULT '' NOT NULL, - PRIMARY KEY (template_id), - UNIQUE tmplte_nm (template_name(255)) -); - - -# Table: 'phpbb_styles_theme' -CREATE TABLE phpbb_styles_theme ( - theme_id mediumint(8) UNSIGNED NOT NULL auto_increment, - theme_name blob NOT NULL, - theme_copyright blob NOT NULL, - theme_path varbinary(100) DEFAULT '' NOT NULL, - PRIMARY KEY (theme_id), - UNIQUE theme_name (theme_name(255)) + style_parent_id int(4) UNSIGNED DEFAULT '0' NOT NULL, + style_parent_tree blob NOT NULL, + PRIMARY KEY (style_id), + UNIQUE style_name (style_name(255)) ); diff --git a/phpBB/install/schemas/mysql_41_schema.sql b/phpBB/install/schemas/mysql_41_schema.sql index 9b32ee19c6..3fd8d4f1d1 100644 --- a/phpBB/install/schemas/mysql_41_schema.sql +++ b/phpBB/install/schemas/mysql_41_schema.sql @@ -761,37 +761,12 @@ CREATE TABLE phpbb_styles ( style_name varchar(255) DEFAULT '' NOT NULL, style_copyright varchar(255) DEFAULT '' NOT NULL, style_active tinyint(1) UNSIGNED DEFAULT '1' NOT NULL, - template_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, - theme_id mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, - PRIMARY KEY (style_id), - UNIQUE style_name (style_name), - KEY template_id (template_id), - KEY theme_id (theme_id) -) CHARACTER SET `utf8` COLLATE `utf8_bin`; - - -# Table: 'phpbb_styles_template' -CREATE TABLE phpbb_styles_template ( - template_id mediumint(8) UNSIGNED NOT NULL auto_increment, - template_name varchar(255) DEFAULT '' NOT NULL, - template_copyright varchar(255) DEFAULT '' NOT NULL, - template_path varchar(100) DEFAULT '' NOT NULL, + style_path varchar(100) DEFAULT '' NOT NULL, bbcode_bitfield varchar(255) DEFAULT 'kNg=' NOT NULL, - template_inherits_id int(4) UNSIGNED DEFAULT '0' NOT NULL, - template_inherit_path varchar(255) DEFAULT '' NOT NULL, - PRIMARY KEY (template_id), - UNIQUE tmplte_nm (template_name) -) CHARACTER SET `utf8` COLLATE `utf8_bin`; - - -# Table: 'phpbb_styles_theme' -CREATE TABLE phpbb_styles_theme ( - theme_id mediumint(8) UNSIGNED NOT NULL auto_increment, - theme_name varchar(255) DEFAULT '' NOT NULL, - theme_copyright varchar(255) DEFAULT '' NOT NULL, - theme_path varchar(100) DEFAULT '' NOT NULL, - PRIMARY KEY (theme_id), - UNIQUE theme_name (theme_name) + style_parent_id int(4) UNSIGNED DEFAULT '0' NOT NULL, + style_parent_tree text NOT NULL, + PRIMARY KEY (style_id), + UNIQUE style_name (style_name) ) CHARACTER SET `utf8` COLLATE `utf8_bin`; diff --git a/phpBB/install/schemas/oracle_schema.sql b/phpBB/install/schemas/oracle_schema.sql index 032c8633dd..8a0f3e56b1 100644 --- a/phpBB/install/schemas/oracle_schema.sql +++ b/phpBB/install/schemas/oracle_schema.sql @@ -1445,17 +1445,15 @@ CREATE TABLE phpbb_styles ( style_name varchar2(765) DEFAULT '' , style_copyright varchar2(765) DEFAULT '' , style_active number(1) DEFAULT '1' NOT NULL, - template_id number(8) DEFAULT '0' NOT NULL, - theme_id number(8) DEFAULT '0' NOT NULL, + style_path varchar2(100) DEFAULT '' , + bbcode_bitfield varchar2(255) DEFAULT 'kNg=' NOT NULL, + style_parent_id number(4) DEFAULT '0' NOT NULL, + style_parent_tree clob DEFAULT '' , CONSTRAINT pk_phpbb_styles PRIMARY KEY (style_id), CONSTRAINT u_phpbb_style_name UNIQUE (style_name) ) / -CREATE INDEX phpbb_styles_template_id ON phpbb_styles (template_id) -/ -CREATE INDEX phpbb_styles_theme_id ON phpbb_styles (theme_id) -/ CREATE SEQUENCE phpbb_styles_seq / @@ -1474,69 +1472,6 @@ END; /* - Table: 'phpbb_styles_template' -*/ -CREATE TABLE phpbb_styles_template ( - template_id number(8) NOT NULL, - template_name varchar2(765) DEFAULT '' , - template_copyright varchar2(765) DEFAULT '' , - template_path varchar2(100) DEFAULT '' , - bbcode_bitfield varchar2(255) DEFAULT 'kNg=' NOT NULL, - template_inherits_id number(4) DEFAULT '0' NOT NULL, - template_inherit_path varchar2(255) DEFAULT '' , - CONSTRAINT pk_phpbb_styles_template PRIMARY KEY (template_id), - CONSTRAINT u_phpbb_tmplte_nm UNIQUE (template_name) -) -/ - - -CREATE SEQUENCE phpbb_styles_template_seq -/ - -CREATE OR REPLACE TRIGGER t_phpbb_styles_template -BEFORE INSERT ON phpbb_styles_template -FOR EACH ROW WHEN ( - new.template_id IS NULL OR new.template_id = 0 -) -BEGIN - SELECT phpbb_styles_template_seq.nextval - INTO :new.template_id - FROM dual; -END; -/ - - -/* - Table: 'phpbb_styles_theme' -*/ -CREATE TABLE phpbb_styles_theme ( - theme_id number(8) NOT NULL, - theme_name varchar2(765) DEFAULT '' , - theme_copyright varchar2(765) DEFAULT '' , - theme_path varchar2(100) DEFAULT '' , - CONSTRAINT pk_phpbb_styles_theme PRIMARY KEY (theme_id), - CONSTRAINT u_phpbb_theme_name UNIQUE (theme_name) -) -/ - - -CREATE SEQUENCE phpbb_styles_theme_seq -/ - -CREATE OR REPLACE TRIGGER t_phpbb_styles_theme -BEFORE INSERT ON phpbb_styles_theme -FOR EACH ROW WHEN ( - new.theme_id IS NULL OR new.theme_id = 0 -) -BEGIN - SELECT phpbb_styles_theme_seq.nextval - INTO :new.theme_id - FROM dual; -END; -/ - - -/* Table: 'phpbb_topics' */ CREATE TABLE phpbb_topics ( diff --git a/phpBB/install/schemas/postgres_schema.sql b/phpBB/install/schemas/postgres_schema.sql index f482920776..c624024362 100644 --- a/phpBB/install/schemas/postgres_schema.sql +++ b/phpBB/install/schemas/postgres_schema.sql @@ -995,47 +995,14 @@ CREATE TABLE phpbb_styles ( style_name varchar(255) DEFAULT '' NOT NULL, style_copyright varchar(255) DEFAULT '' NOT NULL, style_active INT2 DEFAULT '1' NOT NULL CHECK (style_active >= 0), - template_id INT4 DEFAULT '0' NOT NULL CHECK (template_id >= 0), - theme_id INT4 DEFAULT '0' NOT NULL CHECK (theme_id >= 0), + style_path varchar(100) DEFAULT '' NOT NULL, + bbcode_bitfield varchar(255) DEFAULT 'kNg=' NOT NULL, + style_parent_id INT4 DEFAULT '0' NOT NULL CHECK (style_parent_id >= 0), + style_parent_tree varchar(8000) DEFAULT '' NOT NULL, PRIMARY KEY (style_id) ); CREATE UNIQUE INDEX phpbb_styles_style_name ON phpbb_styles (style_name); -CREATE INDEX phpbb_styles_template_id ON phpbb_styles (template_id); -CREATE INDEX phpbb_styles_theme_id ON phpbb_styles (theme_id); - -/* - Table: 'phpbb_styles_template' -*/ -CREATE SEQUENCE phpbb_styles_template_seq; - -CREATE TABLE phpbb_styles_template ( - template_id INT4 DEFAULT nextval('phpbb_styles_template_seq'), - template_name varchar(255) DEFAULT '' NOT NULL, - template_copyright varchar(255) DEFAULT '' NOT NULL, - template_path varchar(100) DEFAULT '' NOT NULL, - bbcode_bitfield varchar(255) DEFAULT 'kNg=' NOT NULL, - template_inherits_id INT4 DEFAULT '0' NOT NULL CHECK (template_inherits_id >= 0), - template_inherit_path varchar(255) DEFAULT '' NOT NULL, - PRIMARY KEY (template_id) -); - -CREATE UNIQUE INDEX phpbb_styles_template_tmplte_nm ON phpbb_styles_template (template_name); - -/* - Table: 'phpbb_styles_theme' -*/ -CREATE SEQUENCE phpbb_styles_theme_seq; - -CREATE TABLE phpbb_styles_theme ( - theme_id INT4 DEFAULT nextval('phpbb_styles_theme_seq'), - theme_name varchar(255) DEFAULT '' NOT NULL, - theme_copyright varchar(255) DEFAULT '' NOT NULL, - theme_path varchar(100) DEFAULT '' NOT NULL, - PRIMARY KEY (theme_id) -); - -CREATE UNIQUE INDEX phpbb_styles_theme_theme_name ON phpbb_styles_theme (theme_name); /* Table: 'phpbb_topics' diff --git a/phpBB/install/schemas/schema_data.sql b/phpBB/install/schemas/schema_data.sql index 3255cafea2..43b09c97f7 100644 --- a/phpBB/install/schemas/schema_data.sql +++ b/phpBB/install/schemas/schema_data.sql @@ -437,13 +437,7 @@ INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) INSERT INTO phpbb_acl_roles (role_name, role_description, role_type, role_order) VALUES ('ROLE_FORUM_NEW_MEMBER', 'ROLE_DESCRIPTION_FORUM_NEW_MEMBER', 'f_', 10); # -- phpbb_styles -INSERT INTO phpbb_styles (style_name, style_copyright, style_active, template_id, theme_id) VALUES ('prosilver', '© phpBB Group', 1, 1, 1); - -# -- phpbb_styles_template -INSERT INTO phpbb_styles_template (template_name, template_copyright, template_path, bbcode_bitfield) VALUES ('prosilver', '© phpBB Group', 'prosilver', 'lNg='); - -# -- phpbb_styles_theme -INSERT INTO phpbb_styles_theme (theme_name, theme_copyright, theme_path) VALUES ('prosilver', '© phpBB Group', 'prosilver'); +INSERT INTO phpbb_styles (style_name, style_copyright, style_active, style_path, bbcode_bitfield, style_parent_id, style_parent_tree) VALUES ('prosilver', '© phpBB Group', 1, 'prosilver', 'kNg=', 0, ''); # -- Forums INSERT INTO phpbb_forums (forum_name, forum_desc, left_id, right_id, parent_id, forum_type, forum_posts, forum_topics, forum_topics_real, forum_last_post_id, forum_last_poster_id, forum_last_poster_name, forum_last_poster_colour, forum_last_post_time, forum_link, forum_password, forum_image, forum_rules, forum_rules_link, forum_rules_uid, forum_desc_uid, prune_days, prune_viewed, forum_parents) VALUES ('{L_FORUMS_FIRST_CATEGORY}', '', 1, 4, 0, 0, 1, 1, 1, 1, 2, 'Admin', 'AA0000', 972086460, '', '', '', '', '', '', '', 0, 0, ''); diff --git a/phpBB/install/schemas/sqlite_schema.sql b/phpBB/install/schemas/sqlite_schema.sql index 56468bcdd9..bd002c93ed 100644 --- a/phpBB/install/schemas/sqlite_schema.sql +++ b/phpBB/install/schemas/sqlite_schema.sql @@ -737,36 +737,13 @@ CREATE TABLE phpbb_styles ( style_name varchar(255) NOT NULL DEFAULT '', style_copyright varchar(255) NOT NULL DEFAULT '', style_active INTEGER UNSIGNED NOT NULL DEFAULT '1', - template_id INTEGER UNSIGNED NOT NULL DEFAULT '0', - theme_id INTEGER UNSIGNED NOT NULL DEFAULT '0' -); - -CREATE UNIQUE INDEX phpbb_styles_style_name ON phpbb_styles (style_name); -CREATE INDEX phpbb_styles_template_id ON phpbb_styles (template_id); -CREATE INDEX phpbb_styles_theme_id ON phpbb_styles (theme_id); - -# Table: 'phpbb_styles_template' -CREATE TABLE phpbb_styles_template ( - template_id INTEGER PRIMARY KEY NOT NULL , - template_name varchar(255) NOT NULL DEFAULT '', - template_copyright varchar(255) NOT NULL DEFAULT '', - template_path varchar(100) NOT NULL DEFAULT '', + style_path varchar(100) NOT NULL DEFAULT '', bbcode_bitfield varchar(255) NOT NULL DEFAULT 'kNg=', - template_inherits_id INTEGER UNSIGNED NOT NULL DEFAULT '0', - template_inherit_path varchar(255) NOT NULL DEFAULT '' + style_parent_id INTEGER UNSIGNED NOT NULL DEFAULT '0', + style_parent_tree text(65535) NOT NULL DEFAULT '' ); -CREATE UNIQUE INDEX phpbb_styles_template_tmplte_nm ON phpbb_styles_template (template_name); - -# Table: 'phpbb_styles_theme' -CREATE TABLE phpbb_styles_theme ( - theme_id INTEGER PRIMARY KEY NOT NULL , - theme_name varchar(255) NOT NULL DEFAULT '', - theme_copyright varchar(255) NOT NULL DEFAULT '', - theme_path varchar(100) NOT NULL DEFAULT '' -); - -CREATE UNIQUE INDEX phpbb_styles_theme_theme_name ON phpbb_styles_theme (theme_name); +CREATE UNIQUE INDEX phpbb_styles_style_name ON phpbb_styles (style_name); # Table: 'phpbb_topics' CREATE TABLE phpbb_topics ( diff --git a/phpBB/language/en/acp/common.php b/phpBB/language/en/acp/common.php index f96947b580..6012c59483 100644 --- a/phpBB/language/en/acp/common.php +++ b/phpBB/language/en/acp/common.php @@ -168,6 +168,8 @@ $lang = array_merge($lang, array( 'ACP_STYLE_COMPONENTS' => 'Style components', 'ACP_STYLE_MANAGEMENT' => 'Style management', 'ACP_STYLES' => 'Styles', + 'ACP_STYLES_CACHE' => 'Purge Cache', + 'ACP_STYLES_INSTALL' => 'Install Styles', 'ACP_SUBMIT_CHANGES' => 'Submit changes', diff --git a/phpBB/language/en/acp/styles.php b/phpBB/language/en/acp/styles.php index 3a96100947..1a6335cdbf 100644 --- a/phpBB/language/en/acp/styles.php +++ b/phpBB/language/en/acp/styles.php @@ -35,15 +35,9 @@ if (empty($lang) || !is_array($lang)) // in a url you again do not need to specify an order e.g., 'Click %sHERE%s' is fine $lang = array_merge($lang, array( - 'ACP_STYLES_EXPLAIN' => 'Here you can manage the available styles on your board. A style consists of a template and theme. You may alter existing styles, delete, deactivate, reactivate, create or import new ones. You can also see what a style will look like using the preview function. The current default style is noted by the presence of an asterisk (*). Also listed is the total user count for each style, note that overriding user styles will not be reflected here.', - 'ACP_TEMPLATES_EXPLAIN' => 'A template set comprises all the markup used to generate the layout of your board. Here you can edit existing template sets, delete, export, import and preview sets. You can also modify the templating code used to generate BBCode.', - 'ACP_THEMES_EXPLAIN' => 'From here you can create, install, edit, delete and export themes. A theme is the combination of colours and images that are applied to your templates to define the basic look of your board. The range of options open to you depends on the configuration of your server and phpBB installation, see the manual for further details. Please note that when creating new themes the use of an existing theme as a basis is optional.', - 'ADD_STYLE' => 'Create style', - 'ADD_STYLE_EXPLAIN' => 'Here you can create a new style. Depending on your server configuration and file permissions you may have additional options. For example you may be able to base this style on an existing one. You may also be able to upload or import (from the store directory) a style archive. If you upload or import an archive the style name will be determined automatically.', + 'ACP_STYLES_EXPLAIN' => 'Here you can manage the available styles on your board. You may alter existing styles, delete, deactivate, reactivate, install new ones. You can also see what a style will look like using the preview function. Also listed is the total user count for each style, note that overriding user styles will not be reflected here.', 'ADD_TEMPLATE' => 'Create template', 'ADD_TEMPLATE_EXPLAIN' => 'Here you can add a new template. Depending on your server configuration and file permissions you may have additional options here. For example you may be able to base this template set on an existing one. You may also be able to upload or import (from the store directory) a template archive. If you upload or import an archive the template name can be optionally taken from the archive name (to do this leave the template name blank).', - 'ADD_THEME' => 'Create theme', - 'ADD_THEME_EXPLAIN' => 'Here you can add a new theme. Depending on your server configuration and file permissions you may have additional options here. For example you may be able to base this theme on an existing one. You may also be able to upload or import (from the store directory) a theme archive. If you upload or import an archive the theme name can be optionally taken from the archive name (to do this leave the theme name blank).', 'ARCHIVE_FORMAT' => 'Archive file type', 'AUTOMATIC_EXPLAIN' => 'Leave blank to attempt automatic detection.', @@ -58,7 +52,9 @@ $lang = array_merge($lang, array( 'CACHE_FILENAME' => 'Template file', 'CACHE_FILESIZE' => 'File size', 'CACHE_MODIFIED' => 'Modified', + 'CANNOT_BE_INSTALLED' => 'Cannot be installed', 'CONFIRM_TEMPLATE_CLEAR_CACHE' => 'Are you sure you wish to clear all cached versions of your template files?', + 'CONFIRM_DELETE_STYLES' => 'Are you sure you wish to delete selected styles?', 'COPYRIGHT' => 'Copyright', 'CREATE_STYLE' => 'Create new style', 'CREATE_TEMPLATE' => 'Create new template set', @@ -66,13 +62,14 @@ $lang = array_merge($lang, array( 'CURRENT_IMAGE' => 'Current image', 'DEACTIVATE_DEFAULT' => 'You cannot deactivate the default style.', + 'DELETE_DEFAULT' => 'You cannot delete the default style.', 'DELETE_FROM_FS' => 'Delete from filesystem', 'DELETE_STYLE' => 'Delete style', 'DELETE_STYLE_EXPLAIN' => 'Here you can remove the selected style. Take care in deleting styles, there is no undo capability.', + 'DELETE_STYLE_FILES_FAILED' => 'Error deleting files for style "%s".', + 'DELETE_STYLE_FILES_SUCCESS' => 'Files for style "%s" have been deleted.', 'DELETE_TEMPLATE' => 'Delete template', 'DELETE_TEMPLATE_EXPLAIN' => 'Here you can remove the selected template set from the database. Please note that there is no undo capability. It is recommended that you first export your set for possible future use.', - 'DELETE_THEME' => 'Delete theme', - 'DELETE_THEME_EXPLAIN' => 'Here you can remove the selected theme from the database. Please note that there is no undo capability. It is recommended that you first export your theme for possible future use.', 'DETAILS' => 'Details', 'DIMENSIONS_EXPLAIN' => 'Selecting yes here will include width/height parameters.', @@ -239,17 +236,10 @@ $lang = array_merge($lang, array( 'INCLUDE_THEME' => 'Include theme', 'INHERITING_FROM' => 'Inherits from', 'INSTALL_STYLE' => 'Install style', - 'INSTALL_STYLE_EXPLAIN' => 'Here you can install a new style and if appropriate the corresponding style elements. If you already have the relevant style elements installed they will not be overwritten. Some styles require existing style elements to already be installed. If you try installing such a style and do not have the required elements you will be notified.', - 'INSTALL_TEMPLATE' => 'Install Template', - 'INSTALL_TEMPLATE_EXPLAIN' => 'Here you can install a new template set. Depending on your server configuration you may have a number of options here.', - 'INSTALL_THEME' => 'Install theme', - 'INSTALL_THEME_EXPLAIN' => 'Here you can install your selected theme. You can edit certain details if you wish or use the installation defaults.', + 'INSTALL_STYLES' => 'Install styles', + 'INSTALL_STYLES_EXPLAIN' => 'Here you can install new styles.<br />If you cannot find a specific style in list below, check to make sure style is already installed. If it is not installed, check if it was uploaded correctly.', 'INSTALLED_STYLE' => 'Installed styles', - 'INSTALLED_TEMPLATE' => 'Installed templates', - 'INSTALLED_THEME' => 'Installed themes', - - 'KEEP_TEMPLATE' => 'Keep “%s” template', - 'KEEP_THEME' => 'Keep “%s” theme', + 'INVALID_STYLE_ID' => 'Invalid style ID.', 'LINE_SPACING' => 'Line spacing', 'LOCALISED_IMAGES' => 'Localised', @@ -257,18 +247,17 @@ $lang = array_merge($lang, array( 'NO_CLASS' => 'Cannot find class in stylesheet.', 'NO_IMAGE' => 'No image', 'NO_IMAGE_ERROR' => 'Cannot find image on filesystem.', + 'NO_MATCHING_STYLES_FOUND' => 'No styles match your query.', 'NO_STYLE' => 'Cannot find style on filesystem.', 'NO_TEMPLATE' => 'Cannot find template on filesystem.', 'NO_THEME' => 'Cannot find theme on filesystem.', 'NO_UNINSTALLED_STYLE' => 'No uninstalled styles detected.', - 'NO_UNINSTALLED_TEMPLATE' => 'No uninstalled templates detected.', - 'NO_UNINSTALLED_THEME' => 'No uninstalled themes detected.', 'NO_UNIT' => 'None', 'ONLY_STYLE' => 'This is the only remaining style, you cannot delete it.', - 'ONLY_TEMPLATE' => 'This is the only remaining template set, you cannot delete it.', - 'ONLY_THEME' => 'This is the only remaining theme, you cannot delete it.', - 'OPTIONAL_BASIS' => 'Optional basis', + + 'PARENT_STYLE_NOT_FOUND' => 'Parent style was not found. This style may not work correctly. Please uninstall it.', + 'PURGED_CACHE' => 'Cache was purged.', 'REFRESH' => 'Refresh', 'REPEAT_NO' => 'None', @@ -282,8 +271,7 @@ $lang = array_merge($lang, array( 'REPLACE_THEME' => 'Replace theme with', 'REPLACE_THEME_EXPLAIN' => 'This theme will replace the one you are deleting in any styles that use it.', 'REPLACE_WITH_OPTION' => 'Replace with “%s”', - 'REQUIRES_TEMPLATE' => 'This style requires the %s template set to be installed.', - 'REQUIRES_THEME' => 'This style requires the %s theme to be installed.', + 'REQUIRES_STYLE' => 'This style requires the style "%s" to be installed.', 'SELECT_IMAGE' => 'Select image', 'SELECT_TEMPLATE' => 'Select template file', @@ -301,21 +289,31 @@ $lang = array_merge($lang, array( 'STYLE_DEACTIVATE' => 'Deactivate', 'STYLE_DEACTIVATED' => 'Style deactivated successfully', 'STYLE_DEFAULT' => 'Make default style', - 'STYLE_DELETED' => 'Style deleted successfully.', + 'STYLE_DEFAULT_CHANGE' => 'Change default style', + 'STYLE_DEFAULT_CHANGE_INACTIVE' => 'You must activate style before making it default style.', + 'STYLE_DELETE_DEPENDENT' => 'Style "%s" cannot be deleted because it has one or more child styles.', + 'STYLE_DELETED' => 'Style "%s" deleted successfully.', 'STYLE_DETAILS_UPDATED' => 'Style edited successfully.', 'STYLE_ERR_ARCHIVE' => 'Please select an archive method.', 'STYLE_ERR_COPY_LONG' => 'The copyright can be no longer than 60 characters.', + 'STYLE_ERR_INVALID_PARENT' => 'Invalid parent style.', 'STYLE_ERR_MORE_ELEMENTS' => 'You must select at least one style element.', 'STYLE_ERR_NAME_CHARS' => 'The style name can only contain alphanumeric characters, -, +, _ and space.', 'STYLE_ERR_NAME_EXIST' => 'A style with that name already exists.', 'STYLE_ERR_NAME_LONG' => 'The style name can be no longer than 30 characters.', - 'STYLE_ERR_NO_IDS' => 'You must select a template and theme for this style.', 'STYLE_ERR_NOT_STYLE' => 'The imported or uploaded file did not contain a valid style archive.', 'STYLE_ERR_STYLE_NAME' => 'You must supply a name for this style.', 'STYLE_EXPORT' => 'Export style', 'STYLE_EXPORT_EXPLAIN' => 'Here you can export a style in the form of an archive. A style does not need to contain all elements but it must contain at least one. For example if you have created a new theme for a commonly used template you could simply export the theme and omit the template. You may select whether to download the file directly or to place it in your store folder for download later or via FTP.', 'STYLE_EXPORTED' => 'Style exported successfully and stored in %s.', + 'STYLE_INSTALLED' => 'Style "%s" has been installed.', + 'STYLE_INSTALLED_EDIT_DETAILS' => '<a href="%s">Click here</a> to edit style details or to change default style.', + 'STYLE_INSTALLED_RETURN_STYLES' => '<a href="%s">Click here</a> to return to installed styles list.', + 'STYLE_INSTALLED_RETURN_UNINSTALLED' => '<a href="%s">Click here</a> to install more styles.', 'STYLE_NAME' => 'Style name', + 'STYLE_NOT_INSTALLED' => 'Style "%s" was not installed.', + 'STYLE_PATH' => 'Style path:', + 'STYLE_PARENT' => 'Parent style:', 'STYLE_TEMPLATE' => 'Template', 'STYLE_THEME' => 'Theme', 'STYLE_USED_BY' => 'Used by (including robots)', @@ -325,8 +323,6 @@ $lang = array_merge($lang, array( 'TEMPLATE_CACHE_EXPLAIN' => 'By default phpBB caches the compiled version of its templates. This decreases the load on the server each time a page is viewed and thus may reduce the page generation time. Here you can view the cache status of each file and delete individual files or the entire cache.', 'TEMPLATE_CACHE_CLEARED' => 'Template cache cleared successfully.', 'TEMPLATE_CACHE_EMPTY' => 'There are no cached templates.', - 'TEMPLATE_DELETED' => 'Template set deleted successfully.', - 'TEMPLATE_DELETE_DEPENDENT' => 'The template set cannot be deleted as there are one or more other template sets inheriting from it:', 'TEMPLATE_DELETED_FS' => 'Template set removed from database but files remain on the filesystem.', 'TEMPLATE_DETAILS_UPDATED' => 'Template details successfully updated.', 'TEMPLATE_EDITOR' => 'Raw HTML template editor', @@ -335,17 +331,12 @@ $lang = array_merge($lang, array( 'TEMPLATE_ERR_CACHE_READ' => 'The cache directory used to store cached versions of template files could not be opened.', 'TEMPLATE_ERR_COPY_LONG' => 'The copyright can be no longer than 60 characters.', 'TEMPLATE_ERR_NAME_CHARS' => 'The template name can only contain alphanumeric characters, -, +, _ and space.', - 'TEMPLATE_ERR_NAME_EXIST' => 'A template set with that name already exists.', 'TEMPLATE_ERR_NAME_LONG' => 'The template name can be no longer than 30 characters.', - 'TEMPLATE_ERR_NOT_TEMPLATE' => 'The archive you specified does not contain a valid template set.', - 'TEMPLATE_ERR_REQUIRED_OR_INCOMPLETE' => 'The new template set requires the template %s to be installed and not inheriting itself.', 'TEMPLATE_ERR_STYLE_NAME' => 'You must supply a name for this template.', - 'TEMPLATE_EXPORT' => 'Export templates', 'TEMPLATE_EXPORT_EXPLAIN' => 'Here you can export a template set in the form of an archive. This archive will contain all the files necessary to install the templates on another board. You may select whether to download the file directly or to place it in your store folder for download later or via FTP.', 'TEMPLATE_EXPORTED' => 'Templates exported successfully and stored in %s.', 'TEMPLATE_FILE' => 'Template file', 'TEMPLATE_FILE_UPDATED' => 'Template file updated successfully.', - 'TEMPLATE_INHERITS' => 'This template sets inherits from %s and thus cannot have a different storage setting than its super template.', 'TEMPLATE_NAME' => 'Template name', 'TEMPLATE_FILE_NOT_WRITABLE'=> 'Unable to write to template file %s. Please check the permissions for the directory and the files.', @@ -373,9 +364,6 @@ $lang = array_merge($lang, array( 'THEME_UPDATED' => 'Theme updated successfully.', 'UNDERLINE' => 'Underline', - 'UNINSTALLED_STYLE' => 'Uninstalled styles', - 'UNINSTALLED_TEMPLATE' => 'Uninstalled templates', - 'UNINSTALLED_THEME' => 'Uninstalled themes', 'UNSET' => 'Undefined', )); diff --git a/phpBB/styles/prosilver/style.cfg b/phpBB/styles/prosilver/style.cfg index 538e167df6..a80f1ed537 100644 --- a/phpBB/styles/prosilver/style.cfg +++ b/phpBB/styles/prosilver/style.cfg @@ -8,7 +8,6 @@ # # At the left is the name, please do not change this # At the right the value is entered -# For on/off options the valid values are on, off, 1, 0, true and false # # Values get trimmed, if you want to add a space in front or at the end of # the value, then enclose the value with single or double quotes. @@ -20,3 +19,10 @@ name = prosilver copyright = © phpBB Group, 2007 version = 3.1.0-dev + +# Defining a different template bitfield +# template_bitfield = lNg= + +# Parent style +# Set value to empty or to this style's name if this style does not have a parent style +parent = prosilver diff --git a/phpBB/styles/prosilver/template/template.cfg b/phpBB/styles/prosilver/template/template.cfg deleted file mode 100644 index 22ca73b487..0000000000 --- a/phpBB/styles/prosilver/template/template.cfg +++ /dev/null @@ -1,30 +0,0 @@ -# -# phpBB Template Configuration File -# -# @package phpBB3 -# @copyright (c) 2006 phpBB Group -# @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 -# -# -# At the left is the name, please do not change this -# At the right the value is entered -# For on/off options the valid values are on, off, 1, 0, true and false -# -# Values get trimmed, if you want to add a space in front or at the end of -# the value, then enclose the value with single or double quotes. -# Single and double quotes do not need to be escaped. -# -# - -# General Information about this template -name = prosilver -copyright = © phpBB Group, 2007 -version = 3.1.0-dev - -# Defining a different template bitfield -template_bitfield = lNg= - -# Template inheritance -# See http://blog.phpbb.com/2008/07/31/templating-just-got-easier/ -# Set value to empty to ignore template inheritance -inherit_from = prosilver diff --git a/phpBB/styles/prosilver/theme/theme.cfg b/phpBB/styles/prosilver/theme/theme.cfg deleted file mode 100644 index eced2a665e..0000000000 --- a/phpBB/styles/prosilver/theme/theme.cfg +++ /dev/null @@ -1,21 +0,0 @@ -# -# phpBB Theme Configuration File -# -# @package phpBB3 -# @copyright (c) 2006 phpBB Group -# @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 -# -# -# At the left is the name, please do not change this -# At the right the value is entered -# For on/off options the valid values are on, off, 1, 0, true and false -# -# Values get trimmed, if you want to add a space in front or at the end of -# the value, then enclose the value with single or double quotes. -# Single and double quotes do not need to be escaped. -# - -# General Information about this theme -name = prosilver -copyright = © phpBB Group, 2007 -version = 3.1.0-dev diff --git a/phpBB/styles/subsilver2/style.cfg b/phpBB/styles/subsilver2/style.cfg index 0804a27082..1a71e7254d 100644 --- a/phpBB/styles/subsilver2/style.cfg +++ b/phpBB/styles/subsilver2/style.cfg @@ -8,7 +8,6 @@ # # At the left is the name, please do not change this # At the right the value is entered -# For on/off options the valid values are on, off, 1, 0, true and false # # Values get trimmed, if you want to add a space in front or at the end of # the value, then enclose the value with single or double quotes. @@ -20,3 +19,10 @@ name = subsilver2 copyright = © 2005 phpBB Group version = 3.1.0-dev + +# Defining a different template bitfield +# template_bitfield = lNg= + +# Parent style +# Set value to empty or to this style's name if this style does not have a parent style +parent = subsilver2 diff --git a/phpBB/styles/subsilver2/template/template.cfg b/phpBB/styles/subsilver2/template/template.cfg deleted file mode 100644 index cf5562a8a4..0000000000 --- a/phpBB/styles/subsilver2/template/template.cfg +++ /dev/null @@ -1,27 +0,0 @@ -# -# phpBB Template Configuration File -# -# @package phpBB3 -# @copyright (c) 2005 phpBB Group -# @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 -# -# -# At the left is the name, please do not change this -# At the right the value is entered -# For on/off options the valid values are on, off, 1, 0, true and false -# -# Values get trimmed, if you want to add a space in front or at the end of -# the value, then enclose the value with single or double quotes. -# Single and double quotes do not need to be escaped. -# -# - -# General Information about this template -name = subsilver2 -copyright = © phpBB Group, 2003 -version = 3.1.0-dev - -# Template inheritance -# See http://blog.phpbb.com/2008/07/31/templating-just-got-easier/ -# Set value to empty to ignore template inheritance -inherit_from = subsilver2 diff --git a/phpBB/styles/subsilver2/theme/theme.cfg b/phpBB/styles/subsilver2/theme/theme.cfg deleted file mode 100644 index 16d66c844a..0000000000 --- a/phpBB/styles/subsilver2/theme/theme.cfg +++ /dev/null @@ -1,21 +0,0 @@ -# -# phpBB Theme Configuration File -# -# @package phpBB3 -# @copyright (c) 2005 phpBB Group -# @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 -# -# -# At the left is the name, please do not change this -# At the right the value is entered -# For on/off options the valid values are on, off, 1, 0, true and false -# -# Values get trimmed, if you want to add a space in front or at the end of -# the value, then enclose the value with single or double quotes. -# Single and double quotes do not need to be escaped. -# - -# General Information about this theme -name = subsilver2 -copyright = © phpBB Group, 2003 -version = 3.1.0-dev |