✏️ 正在编辑: ListOutput.fnc.php
路径:
/home/eblama1/sms.karnplayinland.com/functions/ListOutput.fnc.php
提示:
您可以编辑任何文件(包括二进制文件),但请注意不当修改可能导致文件损坏。
<?php /** * Lists / Listings * * @package RosarioSIS * @subpackage functions * * @since 4.0 Add List Before and After action hooks */ function ListOutput( $result, $column_names, $singular = '.', $plural = '.', $link = [], $group = [], $options = [] ) { global $_ROSARIO; static $list_id = -1; // @since 11.3 Fix list sort, search, page, save when multiple lists on same page $list_id++; $default_options = [ 'save' => '1', 'search' => true, 'count' => true, 'sort' => empty( $group ), 'header_color' => Preferences( 'HEADER' ), // @since 11.3 To disable responsive list layout, add `&LO_disable_responsive=Y` to the URL 'responsive' => empty( $_REQUEST['LO_disable_responsive'] ), // @since 11.7 Allow display of $link['add'] (or remove) on PDF or if not allowed to edit 'add' => ( AllowEdit() && ! isset( $_REQUEST['_ROSARIO_PDF'] ) ), // @since 10.9 Add pagination option (defaults to false) // Deactivated by default as yields strange results when multiple lists on same page. 'pagination' => false, // @since 11.6 Add vertically align list data option (defaults to false) // Use when some columns are text & others input & should be displayed on 1 line only. 'valign-middle' => false, ]; $options = empty( $options ) ? $default_options : array_replace_recursive( $default_options, $options ); $LO_id = issetVal( $_REQUEST['LO_id'], '' ); if ( (int) $LO_id !== $list_id ) { // Request options are not for the current list, set to default. $LO_page = $LO_sort = $LO_dir = $LO_search = $LO_save = ''; } else { // Request options are for the current list, set them. $LO_page = issetVal( $_REQUEST['LO_page'], '' ); $LO_sort = issetVal( $_REQUEST['LO_sort'], '' ); $LO_dir = issetVal( $_REQUEST['LO_dir'], '' ); $LO_search = issetVal( $_REQUEST['LO_search'], '' ); $LO_save = issetVal( $_REQUEST['LO_save'], '' ); } if ( ! $options['add'] && ! empty( $link ) ) { unset( $link['add'] ); unset( $link['remove'] ); } $result_count = $display_count = count( (array) $result ); $num_displayed = 1000; if ( ! empty( $_ROSARIO['SQLLimitForList']['limit'] ) ) { /** * Limit SQL result for List * Improve performance for lists > 1000 results * * @see SQLLimitForList() function * * @since 11.7 */ $num_displayed = $_ROSARIO['SQLLimitForList']['limit']; $sql_count = $_ROSARIO['SQLLimitForList']['sql_count']; // Reset for multiple lists on same page, so we can call SQLLimitForList() again. unset( $_ROSARIO['SQLLimitForList'] ); if ( ( $num_displayed == $result_count || $LO_page > 1 && $result_count < $num_displayed ) && $sql_count ) { // Limit reached, get total count. $result_count = (int) DBGetOne( $sql_count ); if ( $result_count < $num_displayed ) { /** * Fix result count < results (wrong SQL query to COUNT total results) * There's a bug, result count shouldn't be < results. * Can happen for results made of multiple GetStuList() / GetStaffList() calls. * Please make sure you sum SQL queries to COUNT total results before ListOutput(). * @see example in Student_Billing/includes/DailyTransactions.php * * @since 11.7.4 */ $result_count = $num_displayed; } // Force start to 1 as we limited results in SQL. $start = 1; } } // PREPARE LINKS ---. $extra = URLEscape( 'LO_page=' . $LO_page . '&LO_sort=' . $LO_sort . '&LO_dir=' . $LO_dir . '&LO_search=' . $LO_search . ( $list_id ? '&LO_id=' . $list_id : '' ) ); $PHP_tmp_SELF = PreparePHP_SELF( $_REQUEST, [ 'LO_page', 'LO_sort', 'LO_dir', 'LO_search', 'LO_save', 'LO_id', ] ); // END PREPARE LINKS ---. // UN-GROUPING $group_count = empty( $group ) ? false : count( $group ); if ( $group_count && $result_count ) { $group_result = $result; $result = [ 0 => '' ]; foreach ( (array) $group_result as $item1 ) { foreach ( (array) $item1 as $item2 ) { if ( $group_count == 1 ) { $result[] = $item2; continue; } foreach ( (array) $item2 as $item3 ) { if ( $group_count == 2 ) { $result[] = $item3; continue; } foreach ( (array) $item3 as $item4 ) { $result[] = $item4; } } } } unset( $result[0] ); $result_count = $display_count = count( $result ); } // END UN-GROUPING if ( $result_count > $num_displayed && ! $options['pagination'] ) { // Limit to 1000! $display_count = $num_displayed; // Remove results above 1000. $result = array_slice( $result, 0, $num_displayed, true ); } $display_zero = false; // PRINT HEADINGS, PREPARE PDF, AND SORT THE LIST ---. if ( $result_count ) { $remove = 0; if ( isset( $link['remove']['variables'] ) ) { $remove = count( $link['remove']['variables'] ); } $cols = count( $column_names ); // HANDLE SEARCHES ---. if ( $options['search'] && $LO_search !== '' ) { // @since 5.8. $result = _listSearch( $result, $LO_search ); $result_count = $display_count = count( $result ); if ( $result_count ) { $column_names['RELEVANCE'] = _( 'Relevance' ); } if ( $group_count ) { $options['count'] = false; $display_zero = true; } } // END SEARCHES ---. if ( $LO_sort && $result_count > 1 && array_key_exists( $LO_sort, $result[1] ) ) { foreach ( (array) $result as $sort ) { if ( ! isset( $sort[$LO_sort] ) || (string) $sort[$LO_sort] === '' ) { $sort_array[] = ''; continue; } if ( mb_substr( (string) $sort[$LO_sort], 0, 4 ) != '<!--' ) { // Better list sorting by isolating the values $inner_text = trim( strip_tags( preg_replace( '/<script\b[^>]*>(.*?)<\/script>/is', "", (string) $sort[$LO_sort] ) ) ); $sort_array[] = $inner_text !== '' ? $inner_text : trim( $sort[ $LO_sort ] ); continue; } // Use value inside comment to sort! $sort_array[] = trim( mb_substr( $sort[$LO_sort], 4, mb_strpos( $sort[$LO_sort], '-->' ) - 4 ) ); } $dir = $LO_dir == -1 ? SORT_DESC : SORT_ASC; $flag = is_numeric( $sort_array[1] ) ? SORT_NUMERIC : SORT_STRING | SORT_FLAG_CASE; array_multisort( $sort_array, $dir, $flag, $result ); array_unshift( $result, [ 'always_start_list_at_key_1' ] ); unset( $result[0] ); } } // HANDLE MISC ---. if ( empty( $LO_dir ) ) { $LO_dir = 1; } if ( isset( $_REQUEST['_ROSARIO_PDF'] ) && ( ( isset( $cols ) && $cols > 8 ) || ! empty( $_REQUEST['expanded_view'] ) ) ) { // For wkhtmltopdf. $_SESSION['orientation'] = 'landscape'; } // END MISC ---. // HANDLE PAGINATION ---. if ( empty( $LO_page ) || (string) (int) $LO_page != $LO_page || $LO_page < 1 ) { $LO_page = 1; } if ( $result_count ) { if ( $result_count >= $num_displayed ) { $start_display = ( $LO_page - 1 ) * $num_displayed + 1; $stop_display = $start_display + ( $num_displayed - 1 ); $start = issetVal( $start, $start_display ); if ( $stop_display > $result_count ) { $stop_display = $result_count; } $where_message = '<span class="size-1">' . sprintf( _( 'Displaying %d through %d' ), $start_display, $stop_display ) . '.</span> '; if ( $options['pagination'] ) { $total_pages = ceil( $result_count / $num_displayed ); $pagination = [ '<span class="rseparator"></span><span class="size-1">' . _( 'Page' ) . ':' ]; for ( $i = 1; $i <= $total_pages; $i++ ) { if ( $i == $LO_page ) { $pagination[] = ' <b> ' . $i . ' </b> '; continue; } $add_to_url = [ 'LO_page' => $i ]; if ( $list_id ) { $add_to_url['LO_id'] = $list_id; } $page_url = PreparePHP_SELF( $_REQUEST, [ 'LO_search' ], $add_to_url ); $pagination[] = ' <a href="' . $page_url . '"> ' . $i . ' </a> '; } $pagination[] = ' </span>'; $pagination = implode( ' ', $pagination ); // Remove results above $num_displayed (1000). $result = array_slice( $result, $start - 1, $num_displayed ); array_unshift( $result, [ 'always_start_list_at_key_1' ] ); unset( $result[0] ); $display_count = count( $result ); } } // Reset start & stop after removing results above 1000. $start = 1; $stop = $display_count; } // END PAGINATION ---. // List Before hook. do_action( 'functions/ListOutput.fnc.php|list_before' ); // HANDLE SAVING THE LIST ---. if ( $options['save'] && (int) $LO_save === (int) $options['save'] && ! headers_sent() ) { _listSave( $result, $column_names, $singular, $plural, Preferences( 'DELIMITER' ) ); } // END SAVING THE LIST ---. $class = ''; if ( $plural && $plural !== '.' ) { $class = mb_strtolower( preg_replace( '/([^\-a-z0-9]+)/i', '-', $plural ) ); } echo '<div class="list-outer ' . $class . '">'; // SEARCH BOX & MORE HEADERS ---. if ( ! empty( $options['header'] ) ) { echo '<table class="postbox width-100p cellspacing-0 list-header"><thead><tr><th class="center">' . $options['header'] . '</th></tr></thead></table> <div class="postbox">'; } $list_has_nav = false; if ( $options['count'] || $display_zero || ( $options['save'] || $options['search'] && ! isset( $_REQUEST['_ROSARIO_PDF'] ) ) ) { $list_has_nav = true; echo '<table class="list-nav"><tr class="st"><td>'; if ( $options['count'] && $display_count > 0 ) { $result_text = ngettext( ( $singular === '.' ? _( 'Result' ) : $singular ), ( $plural === '.' ? _( 'Results' ) : $plural ), $result_count ); if ( mb_substr( $_SESSION['locale'], 0, 2 ) !== 'de' ) { // We are inside a sentence, convert nouns to lowercase (except for German). $result_text = mb_strtolower( $result_text ); } echo '<span class="size-1">' . sprintf( ngettext( '%d %s was found.', '%d %s were found.', $result_count ), $result_count, $result_text ) . '</span> '; echo empty( $where_message ) ? '' : $where_message; } echo empty( $pagination ) ? '' : $pagination; if ( ( $options['count'] || $display_zero ) && ( $result_count == 0 || $display_count == 0 ) ) { $result_text = ngettext( ( $singular === '.' ? _( 'Result' ) : $singular ), ( $plural === '.' ? _( 'Results' ) : $plural ), 0 ); if ( mb_substr( $_SESSION['locale'], 0, 2 ) !== 'de' ) { // We are inside a sentence, convert nouns to lowercase (except for German). $result_text = mb_strtolower( $result_text ); } // No results message. Default to "Results". echo '<b class="size-1">' . sprintf( _( 'No %s were found.' ), $result_text ) . '</b> '; } if ( $options['save'] && ! isset( $_REQUEST['_ROSARIO_PDF'] ) && $result_count > 0 ) { // Save / Export list button. echo '<a href="' . $PHP_tmp_SELF . '&' . $extra . '&LO_save=' . $options['save'] . '&_ROSARIO_PDF=true" class="list-save" target="_blank"><img src="assets/themes/' . Preferences( 'THEME' ) . '/btn/download.png" class="alignImg" title="' . AttrEscape( _( 'Export list' ) ) . '" alt="' . AttrEscape( _( 'Export list' ) ) . '"></a>'; } echo '</td>'; $colspan = 1; if ( $options['search'] && ! isset( $_REQUEST['_ROSARIO_PDF'] ) && ( $result_count > 0 || $LO_search ) ) { echo '<td class="align-right">'; $add_to_url = []; if ( $list_id ) { $add_to_url['LO_id'] = $list_id; } // Do not remove search URL due to document.URL = 'index.php' in old IE browsers. $search_URL = PreparePHP_SELF( $_REQUEST, [ 'LO_search' ], $add_to_url ); $onkeypress_js = 'LOSearch(event, this.value, ' . json_encode( $search_URL ) . ');'; $onclick_js = 'LOSearch(event, $(\'#LO_search\').val(), ' . json_encode( $search_URL ) . ');'; echo '<input type="text" id="LO_search" name="LO_search" value="' . AttrEscape( DBUnescapeString( $LO_search ) ) . '" placeholder="' . AttrEscape( _( 'Search' ) ) . '" onkeypress="' . AttrEscape( $onkeypress_js ) . '" autocomplete="off"> <img src="assets/themes/' . Preferences( 'THEME' ) . '/btn/visualize.png" onclick="' . AttrEscape( $onclick_js ) . '" class="button" alt="" title="' . AttrEscape( _( 'Search' ) ) . '"> <label for="LO_search" class="a11y-hidden">' . _( 'Search' ) . '</label>'; echo '</td>'; $colspan++; } echo '</tr></table>'; } // END SEARCH BOX & MORE HEADERS ---. if ( $result_count > 0 ) { // List has input? $list_has_input = false; $item = reset( $result ); foreach ( (array) $item as $string ) { if ( $string && ( strpos( $string, '<input' ) !== false || strpos( $string, '<select' ) !== false ) ) { // First row has input. $list_has_input = true; break; } } echo '<div class="list-wrapper"><table class="list widefat' . ( $options['responsive'] && ! isset( $_REQUEST['_ROSARIO_PDF'] ) ? ' rt' : '' ) . ( $options['valign-middle'] ? ' valign-middle' : '' ) . ( ! $list_has_nav ? ' list-no-nav' : '' ) . ( $list_has_input ? ' has-input' : '' ) . '" data-list-id="' . $list_id . '"><thead><tr>'; $i = 1; if ( $remove && ! isset( $_REQUEST['_ROSARIO_PDF'] ) ) { echo '<th class="list-column-delete"><span class="a11y-hidden">' . _( 'Delete' ) . '</span></th>'; $i++; } if ( $cols ) { foreach ( (array) $column_names as $key => $value ) { $direction = $LO_sort == $key ? -1 * (int) $LO_dir : 1; $i++; // @since 10.9 CSS Add .list-column-[column_name] class // Note: you can set column max-width using CSS .list-column-comment { width: 36%; } $class = 'list-column-' . mb_strtolower( preg_replace( '/([^\-a-z0-9]+)/i', '-', $key ) ); if ( isset( $_REQUEST['_ROSARIO_PDF'] ) ) { echo '<td class="' . $class . '" style="background-color:' . $options['header_color'] . '; color:#fff;"><b>' . ParseMLField( $value ) . '</b></td>'; continue; } if ( $options['sort'] // Fix MakeChooseCheckbox() remove parent link to sort column && mb_strpos( $value, 'id="controller' ) === false ) { echo '<th class="' . $class . '"><a href="' . $PHP_tmp_SELF . URLEscape( '&LO_page=' . $LO_page . '&LO_sort=' . $key . '&LO_dir=' . $direction . '&LO_search=' . issetVal( $LO_search, '' ) . ( $list_id ? '&LO_id=' . $list_id : '' ) ) . '">' . ParseMLField( $value ) . '</a></th>'; continue; } echo '<th class="' . $class . '">' . ParseMLField( $value ) . '</th>'; } } echo '</tr></thead><tbody>'; // mab - enable add link as first or last if ( isset( $link['add']['first'] ) && ( $stop - $start + 1 ) >= $link['add']['first'] ) { if ( isset( $link['add']['link'] ) && ! isset( $_REQUEST['_ROSARIO_PDF'] ) ) { echo '<tr class="list-add-row"><td colspan="' . ( $remove ? $cols + 1 : $cols ) . '">' . button( 'add', issetVal( $link['add']['title'], '' ), ( mb_strpos( $link['add']['link'], '"' ) === 0 ? $link['add']['link'] : URLEscape( $link['add']['link'] ) ) ) . '</td></tr>'; } elseif ( isset( $link['add']['span'] ) && ! isset( $_REQUEST['_ROSARIO_PDF'] ) ) { echo '<tr class="list-add-row"><td colspan="' . ( $remove ? $cols + 1 : $cols ) . '">' . button( 'add' ) . $link['add']['span'] . '</td></tr>'; } elseif ( isset( $link['add']['html'] ) && $cols ) { echo '<tr class="list-add-row">'; if ( $remove && ! isset( $_REQUEST['_ROSARIO_PDF'] ) && $link['add']['html']['remove'] ) { echo '<td>' . $link['add']['html']['remove'] . '</td>'; } elseif ( $remove && ! isset( $_REQUEST['_ROSARIO_PDF'] ) ) { echo '<td>' . button( 'add' ) . '</td>'; } foreach ( (array) $column_names as $key => $value ) { echo '<td>' . issetVal( $link['add']['html'][$key], '' ) . '</td>'; } echo '</tr>'; } } for ( $i = $start; $i <= $stop; $i++ ) { $item = $result[$i]; if ( isset( $_REQUEST['_ROSARIO_PDF'] ) && count( $item ) ) { $key = array_keys( $item ); $size = count( $key ); for ( $j = 0; $j < $size; $j++ ) { if ( empty( $item[$key[$j]] ) ) { continue; } $value = preg_replace( '!<select.*selected\>([^<]+)<.*</select\>!i', '\\1', $item[$key[$j]] ); $value = preg_replace( '!<select.*</select\>!i', '', $value ); $item[$key[$j]] = preg_replace( "/<div onclick=[^']+'>/", '', $value ); } } echo '<tr>'; if ( $remove && ! isset( $_REQUEST['_ROSARIO_PDF'] ) ) { $button_title = issetVal( $link['remove']['title'] ); $button_link = empty( $link['remove']['link'] ) ? PreparePHP_SELF( [], array_keys( $link['remove']['variables'] ) ) : URLEscape( $link['remove']['link'] ); foreach ( (array) $link['remove']['variables'] as $var => $val ) { $button_link .= URLEscape( '&' . $var . '=' . issetVal( $item[$val], '' ) ); } echo '<td>' . button( 'remove', $button_title, $button_link ) . '</td>'; } $color = issetVal( $item['row_color'] ); if ( $cols ) { foreach ( (array) $column_names as $key => $value ) { echo $color === Preferences( 'HIGHLIGHT' ) ? '<td class="highlight">' : '<td>'; if ( empty( $link[$key] ) || $item[$key] === false || isset( $_REQUEST['_ROSARIO_PDF'] ) ) { echo issetVal( $item[$key], ' ' ); echo '</td>'; continue; } $link_url = $link[$key]['link']; foreach ( (array) $link[$key]['variables'] as $var => $val ) { // Fix URL encode link variable value to encode "/" $link_url .= '&' . $var . '=' . urlencode( $item[$val] ); } $link_url = URLEscape( $link_url ); if ( ! empty( $link[$key]['js'] ) ) { echo '<a href="#" onclick="' . AttrEscape( 'popups.open(' . json_encode( $link_url ) . '); return false;' ) . '"'; } else { echo '<a href="' . $link_url . '"'; } echo empty( $link[$key]['extra'] ) ? '' : ' ' . $link[$key]['extra']; echo '>'; echo issetVal( $item[$key], '***' ); echo '</a></td>'; } } echo '</tr>'; } if ( ! isset( $link['add']['first'] ) || ( $stop - $start + 1 ) < $link['add']['first'] ) { if ( isset( $link['add']['link'] ) && ! isset( $_REQUEST['_ROSARIO_PDF'] ) ) { echo '<tr class="list-add-row"><td colspan="' . ( $remove ? $cols + 1 : $cols ) . '">' . button( 'add', issetVal( $link['add']['title'], '' ), ( mb_strpos( $link['add']['link'], '"' ) === 0 ? $link['add']['link'] : URLEscape( $link['add']['link'] ) ) ) . '</td></tr>'; } elseif ( isset( $link['add']['span'] ) && ! isset( $_REQUEST['_ROSARIO_PDF'] ) ) { echo '<tr class="list-add-row"><td colspan="' . ( $remove ? $cols + 1 : $cols ) . '">' . button( 'add' ) . $link['add']['span'] . '</td></tr>'; } elseif ( isset( $link['add']['html'] ) && $cols ) { echo '<tr class="list-add-row">'; if ( $remove && ! isset( $_REQUEST['_ROSARIO_PDF'] ) && ! empty( $link['add']['html']['remove'] ) ) { echo '<td>' . $link['add']['html']['remove'] . '</td>'; } elseif ( $remove && ! isset( $_REQUEST['_ROSARIO_PDF'] ) ) { echo '<td>' . button( 'add' ) . '</td>'; } foreach ( (array) $column_names as $key => $value ) { echo '<td>' . issetVal( $link['add']['html'][$key], '' ) . '</td>'; } echo '</tr>'; } } echo '</tbody></table></div>'; echo empty( $options['header'] ) ? '' : '</div>'; } // END PRINT THE LIST ---. // NO RESULTS, BUT HAS ADD FIELDS ---. if ( $result_count == 0 ) { if ( ! empty( $link['add']['link'] ) && ! isset( $_REQUEST['_ROSARIO_PDF'] ) ) { echo '<div class="center">' . button( 'add', issetVal( $link['add']['title'], '' ), ( mb_strpos( $link['add']['link'], '"' ) === 0 ? $link['add']['link'] : URLEscape( $link['add']['link'] ) ) ) . '</div>'; } elseif ( ( ! empty( $link['add']['html'] ) || ! empty( $link['add']['span'] ) ) && count( $column_names ) && ! isset( $_REQUEST['_ROSARIO_PDF'] ) ) { if ( ! empty( $link['add']['html'] ) ) { echo '<div class="list-wrapper"><table class="list widefat has-input'; echo $options['responsive'] ? ' rt' : ''; echo $options['valign-middle'] ? ' valign-middle' : ''; echo $list_has_nav ? '' : ' list-no-nav'; echo '" data-list-id="' . $list_id . '"><thead><tr>'; echo '<th><span class="a11y-hidden">' . _( 'Delete' ) . '</span></th>'; foreach ( (array) $column_names as $value ) { echo '<th>' . ParseMLField( $value ) . '</th>'; } echo '</tr></thead><tbody><tr class="list-add-row"><td>'; echo ! empty( $link['add']['html']['remove'] ) ? $link['add']['html']['remove'] : button( 'add' ); echo '</td>'; foreach ( (array) $column_names as $key => $value ) { echo '<td>' . issetVal( $link['add']['html'][$key], '' ) . '</td>'; } echo '</tr></tbody></table></div>'; } elseif ( ! empty( $link['add']['span'] ) ) { echo '<table class="widefat"><tr class="list-add-row"><td>' . button( 'add' ) . $link['add']['span'] . '</td></tr></table>'; } } echo empty( $options['header'] ) ? '' : '</div>'; } // END NO RESULTS, BUT HAS ADD FIELDS ---. echo '</div>'; // .list-outer. // List After hook. do_action( 'functions/ListOutput.fnc.php|list_after' ); } /** * Reindex Results * Starting from 1 * * Local function * * @example $result = _ReindexResults( $result ); * * @param array $array Array to reindex * @return array Reindexed Array */ function _ReindexResults( $array ) { $new = []; $i = 1; foreach ( (array) $array as $value ) { $new[$i] = $value; $i++; } return $new; } /*class Rosario_List implements Countable { /** * Get the count of elements in the container array. * * @link http://php.net/manual/en/countable.count.php * * @return int */ /*public function count() { return count( $this->container ); } }*/ /** * Search List * * Local function * * @example $result = _listSearch( $result, $LO_search ); * @since 5.8 * * @param array $result ListOutput result. * @param string $LO_search ListOutput search term. * @return array $result Searched result. */ function _listSearch( $result, $LO_search ) { $result_count = count( $result ); $search_term = trim( mb_strtolower( DBUnescapeString( $LO_search ) ) ); $terms = []; if ( mb_substr( $search_term, 0, 1 ) != '"' || mb_substr( $search_term, -1, 1 ) != '"' ) { $search_term = str_replace( '"', '', $search_term ); while ( $space_pos = mb_strpos( $search_term, ' ' ) ) { $terms[mb_substr( $search_term, 0, $space_pos )] = 1; $search_term = mb_substr( $search_term, ( $space_pos + 1 ) ); } $terms[trim( $search_term )] = 1; } elseif ( mb_strlen( $search_term ) > 2 ) { // Search "expression". $search_term = str_replace( '"', '', $search_term ); $terms[$search_term] = 1; } /* TRANSLATORS: List of words ignored during search operations */ $ignored_words = explode( ', ', _( 'of, the, a, an, in' ) ); foreach ( $ignored_words as $word ) { unset( $terms[trim( $word )] ); } foreach ( (array) $result as $key => $value ) { $values[$key] = 0; foreach ( (array) $value as $val ) { if ( empty( $val ) && $val !== '0' ) { continue; } // FJ better list searching by isolating the values. $val = mb_strtolower( strip_tags( preg_replace( '/<script\b[^>]*>(.*?)<\/script>/is', "", $val ) ) ); if ( $search_term == $val ) { // +25 if Exact match. $values[$key] += 25; continue; } foreach ( $terms as $term => $one ) { if ( mb_strpos( $val, $term ) !== false ) { // +3 for each Term found. $values[$key] += 3; } } } if ( $values[$key] == 0 ) { unset( $values[$key] ); unset( $result[$key] ); $result_count--; } } // Add Relevance column. if ( ! $result_count ) { return $result; } array_multisort( $values, SORT_DESC, $result ); $result = _ReindexResults( $result ); $values = _ReindexResults( $values ); $last_value = 1; $scale = ( 100 / $values[$last_value] ); for ( $i = $last_value; $i <= $result_count; $i++ ) { $score = (int) ( $values[$i] * $scale ); $result[$i]['RELEVANCE'] = '<div class="bar relevance" style="width:' . $score . 'px;">' . $score . '</div>'; } return $result; } /** * Save / Export List to CSV (OpenOffice), Tab (Excel) or XML * * Local function * * @example _listSave( $result, $column_names, Preferences( 'DELIMITER' ) ); * @since 2.9 * @since 5.8 Export list to Excel using MicrosoftXML (more reliable). * @since 10.9.5 Security: prevent CSV Injection via formulas * @since 11.2.1 Excel & CSV: replace line breaks (br) with "\n" instead of space * @since 11.3 Export list to Excel using SimpleXLSXGen (more reliable) * * @param array $result ListOutput $result * @param array $column_names ListOutput $column_names * @param string $singular ListOutput $singular * @param string $plural ListOutput $plural * @param string $delimiter CSV|Tab|XML * @return void Outputs file and exits */ function _listSave( $result, $column_names, $singular, $plural, $delimiter ) { $format_value = function ( $value ) { $value = trim( preg_replace( '/ +/', // Remove double spaces. ' ', str_replace( [ "\r", "\n", "\t", '[br][br]' ], // Convert new lines to [br], remove tabs. [ '', '[br]', '', '[br]' ], html_entity_decode( // Decode HTML entities. strip_tags( // Remove HTML tags. str_ireplace( [ ' ', '<br />', '<br>' ], // Convert to space, <br> to [br]. [ ' ', '[br]', '[br]' ], $value ) ), ENT_QUOTES ) ) ) ); // Remove first [br] if any. return mb_strpos( $value, '[br]' ) === 0 ? mb_substr( $value, 4 ) : $value; }; switch ( $delimiter ) { case 'CSV': $extension = 'csv'; $delimiter = ','; break; case 'XML': $extension = 'xml'; $delimiter = ""; break; default: // Tab. $extension = 'xlsx'; $delimiter = "\t"; break; } // Clear output. ob_end_clean(); $formatted_columns = $formatted_result = []; // Format Columns. foreach ( (array) $column_names as $column ) { if ( $column !== '' ) { $column = ParseMLField( $column ); $column = $format_value( $column ); $column = str_replace( '[br]', ' ', $column ); } if ( $extension === 'csv' ) { $column = '"' . str_replace( '"', '""', $column ) . '"'; } $formatted_columns[] = $column; } $i = $extension === 'xlsx' ? 1 : 0; $formula_start_characters = [ '=', '-', '+', '@', "\t", "\r" ]; // Format Results. foreach ( (array) $result as $item ) { $formatted_result[$i] = []; foreach ( (array) $column_names as $key => $value ) { $value = issetVal( $item[$key], '' ); if ( $value !== '' ) { $value = preg_replace( '!<select.*selected\>([^<]+)<.*</select\>!i', '\\1', $value ); $value = preg_replace( '!<select.*</select\>!i', '', $value ); $value = $format_value( $value ); $replace_br = $extension === 'xml' ? '[br]' : "\n"; $value = str_replace( '[br]', $replace_br, $value ); } if ( $extension === 'csv' && mb_strlen( $value ) > 1 && in_array( substr( $value, 0, 1 ), $formula_start_characters, true ) ) { /** * Security: prevent CSV Injection via formulas * Use single quote to escape formulas * * @since 10.9.5 * * @link https://symfony.com/blog/cve-2021-41270-prevent-csv-injection-via-formulas */ $value = "'" . $value; } if ( $extension === 'csv' ) { $value = '"' . str_replace( '"', '""', $value ) . '"'; } $formatted_result[$i][] = $value; } $i++; } // Generate output. if ( $extension === 'xlsx' ) { /** * Export list to Excel using SimpleXLSXGen (more reliable) * * @uses SimpleXLSXGen class. * * @since 11.3 * * @link https://github.com/shuchkin/simplexlsxgen */ require_once 'classes/SimpleXLSXGen/SimpleXLSXGen.php'; $formatted_rows = array_merge( [ $formatted_columns ], $formatted_result ); $xlsx = Shuchkin\SimpleXLSXGen::fromArray( $formatted_rows ); $xlsx->setTitle( ProgramTitle() ); $xlsx->downloadAs( ProgramTitle() . '.' . $extension ); exit(); } elseif ( $extension === 'csv' ) { // 1st line: Columns. $output = implode( $delimiter, $formatted_columns ); $output .= "\n"; // Then values. foreach ( $formatted_result as $result_line ) { $output .= implode( $delimiter, $result_line ); $output .= "\n"; } } // XML. else { $sanitize_xml_tag = function ( $name ) { // Remove punctuation excepted underscores, points and dashes. $name = preg_replace( "/(?![.\-_])\p{P}/u", '', $name ); // Lowercase and replace spaces by underscores. $name = mb_strtolower( str_replace( ' ', '_', $name ) ); if ( (string) (int) mb_substr( $name, 0, 1 ) === mb_substr( $name, 0, 1 ) ) { // Name cannot start with a number. $name = '_' . $name; } return $name; }; $elements = 'items_set'; $element = 'item'; if ( $plural !== '.' ) { // Sanitize XML tag names. $elements = $sanitize_xml_tag( $plural ); $element = $sanitize_xml_tag( $singular ); } $output = '<?xml version="1.0" encoding="UTF-8"?>' . "\n" . '<' . $elements . '>' . "\n"; foreach ( $formatted_result as $result_line ) { $output .= "\t" . '<' . $element . '>' . "\n"; foreach ( $result_line as $key => $value ) { if ( $formatted_columns[$key] === '' ) { $column = 'column_' . ( $key + 1 ); } else { // Sanitize XML tag names. $column = $sanitize_xml_tag( $formatted_columns[$key] ); } // http://stackoverflow.com/questions/1091945/what-characters-do-i-need-to-escape-in-xml-documents $value = str_replace( '[br]', '<br>', AttrEscape( $value ) ); $output .= "\t\t" . '<' . $column . '>' . $value . '</' . $column . '>' . "\n"; } $output .= "\t" . '</' . $element . '>' . "\n"; } $output .= '</' . $elements . '>'; } // Download file header( "Cache-Control: public" ); header( "Content-Type: application/" . $extension ); header( "Content-Length: " . strlen( $output ) ); header( "Content-Disposition: inline; filename=\"" . ProgramTitle() . "." . $extension . "\"\n" ); echo $output; exit(); }
💾 保存文件
← 返回文件管理器