# # set_report_variable() # # Purpose: This sets a single variable in a report # # Parameters: profile: the profile # report_name: the name of the report # varname: the name of the variable # varvalue: the value to set varname to # subroutine(set_report_variable(node profile, node report, string varname, string varvalue), ( # Get the full report nodename # string reports = profile . ".statistics.reports"; # string report = reports . "." . report_name; (report . "." . varname) = varvalue; )); #### set_report_variable() #### # # set_report_element_variable() # # Purpose: This sets a single variable in a report element # # Parameters: profile: the profile # report_name: the name of the report (and of the report element) # varname: the name of the variable to set # varvalue: the value to set varname to # #subroutine(set_report_element_variable(node profile, string report_name, string report_element_name, string varname, string varvalue), ( subroutine(set_report_element_variable(node profile, node report_element, string varname, string varvalue), ( # Get the full report nodename # string reports = profile . ".statistics.reports"; # string report = reports . "." . report_name; # string report_element = report . ".report_elements." . report_element_name; (report_element . "." . varname) = varvalue; )); #### set_report_element_variable() #### # # place_report() # # Purpose: This puts a report in the proper group in statistics.reports_menu # # Parameters: profile: the profile # report_name: the name of the report # report_label: the label of the report # report_groups: the report group information to use # reports_menu_label: the label of the report in the reports menu # subroutine(place_report(node profile, string report_name, string report_label, node report_groups, string reports_menu_label), ( # Get the root of the report name (strip off suffix) string report_name_root = report_name; if (ends_with(report_name, "_bottom_level_items")) then ( report_name_root = substr(report_name, 0, length(report_name) - length("_bottom_level_items")); ); # Look through all report groups for a place to put this report bool placed_report; node group; foreach group report_groups ( # Of this report is part of this group, put it there if (node_exists(group . "." . report_name_root)) then ( # If this report is "false" in the group, don't include it in rhe reports_menu if ($(group . "." . report_name_root) ne "false") then ( string group_name = node_name(group); string group_node = profile . ".statistics.reports_menu." . group_name; (group_node . ".type") = "group"; if (!subnode_exists(group_node, "label")) then (group_node . ".label") = "$lang_stats.menu.groups." . group_name; string report_node = group_node . ".items." . report_name; (report_node . ".type") = "view"; (report_node . ".label") = report_label; (report_node . ".view_name") = report_name; ); # if report present placed_report = true; ); # if report is in this group # Check in the "items" node to see if it's there (manual report menu layout) else if (node_exists(group . ".items." . report_name_root)) then ( string group_name = node_name(group); string group_node = profile . ".statistics.reports_menu." . group_name; (group_node . ".type") = "group"; if (!subnode_exists(group_node, "label")) then (group_node . ".label") = "$lang_stats.menu.groups." . group_name; string report_node = group_node . ".items." . report_name; (report_node . ".type") = "view"; (report_node . ".label") = reports_menu_label; (report_node . ".view_name") = report_name; placed_report = true; ); # if report is in this group ); # foreach group # Return whether we placed a report or not placed_report; )); #### place_report() #### # # add_simple_report_element() # # Purpose: This adds a report element to a profile # # Parameters: profile: the profile # report_name: the name of the report # report_label: the label of the report # report_element_name: the name of the report element # report_element_label: the label of the report element # type: the report type # reports_menu_label: the label of the report in the reports menu # subroutine(add_simple_report_element(node profile, string report_name, string report_label, string report_element_name, string report_element_label, string type, string reports_menu_label), ( # Don't place subreports of the single-page summary if ((report_name eq report_element_name) or ((report_name eq "single_page_summary") and (report_element_name eq "overview"))) then ( # Find the report group this belongs in, and add this item to the group if we find one bool found_in_group = false; # If there is a report_groups node in the plug-in, use it node report_groups; bool placed = false; if (node_exists(profile . ".create_profile_wizard_options.report_groups")) then ( placed = place_report(profile, report_name, report_label, profile . ".create_profile_wizard_options.report_groups", reports_menu_label); ); # Otherwise, use the default report groups node if (!placed) then placed = place_report(profile, report_name, report_label, "templates.admin.profiles.report_groups", reports_menu_label); # If we didn't find a group to put the report in, put it at the top level if (!placed) then ( string report_node = profile . ".statistics.reports_menu." . report_name; (report_node . ".type") = "view"; (report_node . ".label") = report_label; (report_node . ".view_name") = report_name; ); # if !found_in_group ); # if not single-page summary (profile . ".statistics.reports." . report_name . ".report_elements." . report_element_name) = ""; node report = profile . ".statistics.reports." . report_name; node report_element = report . ".report_elements." . report_element_name; # Set the label of the report set_report_variable(profile, report, "label", report_label); # Set the label of the report element set_report_element_variable(profile, report_element, "label", report_element_label); # Set the type set_report_element_variable(profile, report_element, "type", type); )); #### add_simple_report_element() #### # # add_nonnumerical_column_to_table() # # Purpose: This adds a non-numerical column to a table in a report element # # Parameters: profile: the profile # report_name: the name of the report # report_element: the name of the report element # columnname: the name of the column to add # dbfield: the node of the database field to add a column for # # Add a non-numerical column to a report element table subroutine(add_nonnumerical_column_to_table(node profile, node report_element, string columnname, string dbfieldname), ( string columnnode = "columns." . columnname . "."; set_report_element_variable(profile, report_element, columnnode . "type", "string"); set_report_element_variable(profile, report_element, columnnode . "visible", "true"); set_report_element_variable(profile, report_element, columnnode . "field_name", dbfieldname); set_report_element_variable(profile, report_element, columnnode . "data_type", "string"); string header_label; if (node_exists(profile . ".database.fields." . dbfieldname . ".label")) then header_label = "{=capitalize(database.fields." . dbfieldname . ".label)=}"; else if (node_exists("lang_stats.field_labels." . dbfieldname)) then header_label = "$lang_stats.field_labels." . dbfieldname; else header_label = dbfieldname; string display_format_type_node = profile . ".database.fields." . dbfieldname . ".display_format_type"; string display_format_type; if (node_exists(display_format_type_node)) then display_format_type = $display_format_type_node; else if ((dbfieldname eq "start_time") or (dbfieldname eq "end_time")) then ( display_format_type = "date_time"; header_label = "$lang_stats.individual_sessions." . dbfieldname; ) else display_format_type = "string"; if (dbfieldname eq "user") then header_label = "$lang_stats.individual_sessions." . dbfieldname; set_report_element_variable(profile, report_element, columnnode . "header_label", header_label); set_report_element_variable(profile, report_element, columnnode . "display_format_type", display_format_type); set_report_element_variable(profile, report_element, columnnode . "main_column", "true"); )); #### add_nonnumerical_column_to_table() #### # # add_numerical_column_to_table() # # Purpose: This adds a numerical column to a table in a report element # # Parameters: profile: the profile # report_name: the name of the report # report_element: the name of the report element # columnname: the name of the column to add # dbfield: the name of the database field to add a column for # sort_dbfield: the name of main numerical database field (the default sort field) # add_graph: true if a graph for the main numerical database field should be shown # karl # subroutine(add_numerical_column_to_table(node profile, node report_element, string columnname, string dbfield, string sort_dbfieldname, bool add_graph), ( string columnnode = "columns." . columnname . "."; # Compute the data type and display format type for this column. string data_type; string display_format_type; string numerical_field_name; string header_label; if ((dbfield eq "sessions") or (dbfield eq "events")) then ( data_type = "int"; display_format_type = "integer"; numerical_field_name = dbfield; header_label = "$lang_stats.field_labels." . numerical_field_name; ) else if (dbfield eq "time_spent") then ( data_type = "int"; display_format_type = "duration_compact"; numerical_field_name = dbfield; header_label = "$lang_stats.field_labels." . numerical_field_name; ) else ( data_type = $(dbfield . ".type"); display_format_type = $(dbfield . ".display_format_type"); numerical_field_name = node_name(dbfield); header_label = "{=capitalize(database.fields." . numerical_field_name . ".label)=}"; ); # Set the columns variables set_report_element_variable(profile, report_element, columnnode . "header_label", header_label); set_report_element_variable(profile, report_element, columnnode . "type", "number"); set_report_element_variable(profile, report_element, columnnode . "show_number_column", "true"); set_report_element_variable(profile, report_element, columnnode . "show_percent_column", (numerical_field_name eq sort_dbfieldname)); set_report_element_variable(profile, report_element, columnnode . "show_bar_column", (numerical_field_name eq sort_dbfieldname)); set_report_element_variable(profile, report_element, columnnode . "visible", "true"); set_report_element_variable(profile, report_element, columnnode . "field_name", numerical_field_name); set_report_element_variable(profile, report_element, columnnode . "data_type", data_type); set_report_element_variable(profile, report_element, columnnode . "display_format_type", display_format_type); if (add_graph) then ( set_report_element_variable(profile, report_element, columnnode . "show_graph", "true"); ); )); #### add_numerical_column_to_table() #### # # add_table_report_element() # # Purpose: This adds a standard table report (based on a database field) to a profile. # # Parameters: profile: the profile # report_name: the name of the report to add # report_label: the label of the report to add # report_element_name: the name of the report element to add # report_element_label: the label of the report element to add # dbfieldname: the name of the database field to base the table on # second_column_dbfieldname: name of a dbfield for a second column; "" if none # main_numerical_dbfieldname: the main numerical database field # sort_dbfield: the name of main numerical database field (the default sort field) # sort_direction: the direction of sorting # only_bottom_level_items: true of the table should show bottom-level items only (false for hierarchical) # subroutine(add_table_report_element(node profile, string report_name, string report_label, string report_element_name, string report_element_label, string dbfieldname, string second_column_dbfieldname, string main_numerical_dbfieldname, string sort_dbfieldname, string sort_direction, bool only_bottom_level_items), ( add_simple_report_element(profile, report_name, report_label, report_element_name, report_element_label, "table", report_label); # Get the full report nodename node reports = profile . ".statistics.reports"; node report = reports . "." . report_name; node report_element = report . ".report_elements." . report_element_name; # Set the general variables set_report_element_variable(profile, report_element, "database_field_name", dbfieldname); set_report_element_variable(profile, report_element, "sort_by", sort_dbfieldname); set_report_element_variable(profile, report_element, "sort_direction", sort_direction); set_report_element_variable(profile, report_element, "show_omitted_items_row", "true"); set_report_element_variable(profile, report_element, "omit_parenthesized_items", "true"); set_report_element_variable(profile, report_element, "show_totals_row", "true"); set_report_element_variable(profile, report_element, "starting_row", 1); # Set ending_row based on the report type if (report_element_name eq "day_of_week") then set_report_element_variable(profile, report_element, "ending_row", 7); else if (report_element_name eq "hour_of_day") then set_report_element_variable(profile, report_element, "ending_row", 24); else set_report_element_variable(profile, report_element, "ending_row", 10); set_report_element_variable(profile, report_element, "only_bottom_level_items", only_bottom_level_items); # Turn on graphing, if appropriate bool show_graph = ((dbfieldname eq "date_time") or (dbfieldname eq "day_of_week") or (dbfieldname eq "hour_of_day")); # Since version 7.0.11 "show_graph = true" needs to be added into the report elements columns node, # the same way as i.e. show_bar_column = true # set_report_element_variable(profile, report_element, "show_graph", show_graph); # if (show_graph) then ( # set_report_element_variable(profile, report_element, "graph.numerical_fields." . main_numerical_dbfieldname, true); # ); # Add the non-numerical column int columnnum = 0; add_nonnumerical_column_to_table(profile, report_element, columnnum, dbfieldname); columnnum++; # Add the second non-numerical column, if any if (second_column_dbfieldname ne "") then ( # Add the column add_nonnumerical_column_to_table(profile, report_element, columnnum, second_column_dbfieldname); columnnum++; # Add the subtable options set_report_element_variable(profile, report_element, "sub_table.ending_row", 10); set_report_element_variable(profile, report_element, "sub_table.omit_parenthesized_items", true); set_report_element_variable(profile, report_element, "sub_table.show_omitted_items_row", true); set_report_element_variable(profile, report_element, "sub_table.show_averages_row", false); set_report_element_variable(profile, report_element, "sub_table.show_totals_row", true); ); # if second column debug_message("Adding numerical columns to '" . report_element . "'\n"); # Add all numerical columns bool add_graph; node dbfield; foreach dbfield (profile . ".database.fields") ( if (node_value(subnode_by_name(dbfield, "type")) ne "string") then ( # If this field is in the field associations list for the main database field, # or if there is no field associations list, include it in the table. if (!node_exists(profile . '.create_profile_wizard_options.database_field_associations.' . dbfieldname) or node_exists(profile . '.create_profile_wizard_options.database_field_associations.' . dbfieldname . '.' . node_name(dbfield))) then ( add_graph = false; # debug_message("@@@@ @@@@ dbfield: " . node_name(dbfield) . "\n"); # debug_message("@@@@ @@@@ main_numerical_dbfieldname: " . main_numerical_dbfieldname . "\n\n"); debug_message(" Adding numerical column '" . node_name(dbfield) . "'\n"); if (show_graph and (node_name(dbfield) eq main_numerical_dbfieldname)) then (add_graph = true;); add_numerical_column_to_table(profile, report_element, columnnum, dbfield, sort_dbfieldname, add_graph); columnnum++; ); # if field associated else ( debug_message(" Not adding column '" . node_name(dbfield) . "' (not in field associations)\n"); # If this is the sort field, and it's not being put in the table, then we need to sort by something else; # use the first field if (node_name(dbfield) eq sort_dbfieldname) then ( debug_message(" ... Uh oh, that's the default sort field; we need to find another field to sort on.\n"); sort_dbfieldname = node_name(subnode_by_number(profile . '.create_profile_wizard_options.database_field_associations.' . dbfieldname, 0)); set_report_element_variable(profile, report_element, "sort_by", sort_dbfieldname); debug_message(" ... sorting on '" . sort_dbfieldname . "'\n"); ); # if sort field ); # if field not associated ); # if numerical ); # for dbfields )); #### add_table_report_element() #### # # add_entry_exit_pages_report() # # Purpose: This adds an entry_pages or exit_pages report to a profile # # Parameters: profile: the profile # report_name: "entry_pages" or "exit_pages" # subroutine(add_entry_exit_pages_report(node profile, string report_name), ( string report_label = "$lang_stats." . report_name . ".label"; add_simple_report_element(profile, report_name, report_label, report_name, report_label, report_name, report_label); # Get the full report nodename string reports = profile . ".statistics.reports"; node report = reports . "." . report_name; node report_element = report . ".report_elements." . report_name; set_report_element_variable(profile, report_element, "sort_by", "sessions"); set_report_element_variable(profile, report_element, "sort_direction", "descending"); set_report_element_variable(profile, report_element, "show_omitted_items_row", "true"); set_report_element_variable(profile, report_element, "show_totals_row", "true"); set_report_element_variable(profile, report_element, "show_graph", "false"); # Add the table columns column add_nonnumerical_column_to_table(profile, report_element, 0, "page"); add_numerical_column_to_table(profile, report_element, 1, "sessions", "sessions", false); )); #### add_entry_exit_pages_report() #### # # add_session_pages_report() # # Purpose: This adds a session_pages report to a profile # # Parameters: profile: the profile to add the report to # subroutine(add_session_pages_report(node profile), ( string report_name = "session_pages"; string report_label = "$lang_stats." . report_name . ".label"; add_simple_report_element(profile, report_name, report_label, report_name, report_label, report_name, report_label); # Get the full report nodename node reports = profile . ".statistics.reports"; node report = reports . "." . report_name; node report_element = report . ".report_elements." . report_name; set_report_element_variable(profile, report_element, "sort_by", "sessions"); set_report_element_variable(profile, report_element, "sort_direction", "descending"); set_report_element_variable(profile, report_element, "show_omitted_items_row", "true"); set_report_element_variable(profile, report_element, "show_totals_row", "true"); set_report_element_variable(profile, report_element, "show_graph", "false"); # Add the table columns column add_nonnumerical_column_to_table(profile, report_element, 0, "page"); add_numerical_column_to_table(profile, report_element, 1, "sessions", "sessions", false); add_numerical_column_to_table(profile, report_element, 2, "events", "events", false); add_numerical_column_to_table(profile, report_element, 3, "time_spent", "time_spent", false); )); #### add_session_pages_report() #### # # add_session_users_report() # # Purpose: This adds a session_users report to a profile # # Parameters: profile: the profile to add the report to # subroutine(add_session_users_report(node profile), ( string report_name = "session_users"; string report_label = "$lang_stats." . report_name . ".label"; add_simple_report_element(profile, report_name, report_label, report_name, report_label, report_name, report_label); # Get the full report nodename node reports = profile . ".statistics.reports"; node report = reports . "." . report_name; node report_element = report . ".report_elements." . report_name; set_report_element_variable(profile, report_element, "sort_by", "sessions"); set_report_element_variable(profile, report_element, "sort_direction", "descending"); set_report_element_variable(profile, report_element, "show_omitted_items_row", "true"); set_report_element_variable(profile, report_element, "show_totals_row", "true"); set_report_element_variable(profile, report_element, "show_graph", "false"); # Add the table columns column add_nonnumerical_column_to_table(profile, report_element, 0, "user"); add_numerical_column_to_table(profile, report_element, 1, "sessions", "sessions", false); add_numerical_column_to_table(profile, report_element, 2, "events", "events", false); add_numerical_column_to_table(profile, report_element, 3, "time_spent", "time_spent", false); )); #### add_session_users_report() #### # # add_individual_sessions_report() # # Purpose: This adds an individual_sessions report to a profile # # Parameters: profile: the profile to add the report to # subroutine(add_individual_sessions_report(node profile), ( string report_name = "individual_sessions"; string report_label = "$lang_stats." . report_name . ".label"; add_simple_report_element(profile, report_name, report_label, report_name, report_label, report_name, report_label); # Get the full report nodename node reports = profile . ".statistics.reports"; node report = reports . "." . report_name; node report_element = report . ".report_elements." . report_name; set_report_element_variable(profile, report_element, "sort_by", "events"); set_report_element_variable(profile, report_element, "sort_direction", "descending"); set_report_element_variable(profile, report_element, "show_omitted_items_row", "true"); set_report_element_variable(profile, report_element, "show_totals_row", "true"); set_report_element_variable(profile, report_element, "show_graph", "false"); # Add the table columns column add_nonnumerical_column_to_table(profile, report_element, 0, "session_id"); add_nonnumerical_column_to_table(profile, report_element, 1, "user"); add_numerical_column_to_table(profile, report_element, 2, "events", "events", false); add_nonnumerical_column_to_table(profile, report_element, 3, "start_time"); add_nonnumerical_column_to_table(profile, report_element, 4, "end_time"); add_numerical_column_to_table(profile, report_element, 5, "time_spent", "time_spent", false); )); #### add_individual_sessions_report() #### # # add_session_reports() # # Purpose: This adds all the standard session reports to a profile # # Parameters: profile: the profile to add the reports to # subroutine(add_session_reports(node profile), ( bool show_session_reports = !node_exists(profile . ".not_supported.sessions") or !$(profile . ".not_supported.sessions"); bool show_session_pages_reports = !node_exists(profile . ".not_supported.sessionpages") or !$(profile . ".not_supported.sessionpages"); # Don't show session reports if the field options don't exist # if (node_exists(profile . ".log.field_options") and # node_exists(profile . ".log.field_options.sessions_page_field") and # node_exists(profile . ".log.field_options.sessions_visitor_id_field") and # node_exists(profile . ".log.field_options.sessions_event_field")) then ( ) # If the session_page_field is not defined at all, don't display session information if (!node_exists(profile . ".log.field_options.sessions_page_field") or (node_value(profile . ".log.field_options.sessions_page_field") eq "none")) then ( show_session_pages_reports = false; ) # Don't show session reports if the sessions page field doesn't exist in the database fields list else if (!node_exists(profile . '.database.fields.' . node_value(profile . ".log.field_options.sessions_page_field"))) then ( show_session_pages_reports = false; ); # If the session_visitor_id_field is not defined at all, don't display session information if (!node_exists(profile . ".log.field_options.sessions_visitor_id_field") or (node_value(profile . ".log.field_options.sessions_visitor_id_field") eq "none")) then ( debug_message("Disabling session reports because visitor_id field does not exist\n"); show_session_reports = false; ) # Don't show session reports if the sessions visitor_id field doesn't exist in the database fields list else if (!node_exists(profile . '.database.fields.' . node_value(profile . ".log.field_options.sessions_visitor_id_field"))) then ( debug_message("Disabling session reports because visitor_id field does not exist in db fields\n"); show_session_reports = false; ); # If the session_event_field is not defined at all, don't display session information if (!node_exists(profile . ".log.field_options.sessions_event_field") or (node_value(profile . ".log.field_options.sessions_event_field") eq "none")) then ( debug_message("Disabling session reports because event field does not exist\n"); show_session_reports = false; ) # Don't show session reports if the sessions event field doesn't exist in the database fields list else if (!node_exists(profile . '.database.fields.' . node_value(profile . ".log.field_options.sessions_event_field"))) then ( debug_message("Disabling session reports because event field does not exist in db fields\n"); show_session_reports = false; ); # else # show_session_reports = false; debug_message("6: show_session_reports: $show_session_reports...\n"); if (show_session_reports) then ( string report_label = "$lang_stats.sessions_overview.label"; add_simple_report_element(profile, "sessions_overview", report_label, "sessions_overview", report_label, "sessions_overview", report_label); if (show_session_pages_reports) then ( add_entry_exit_pages_report(profile, "entry_pages"); add_entry_exit_pages_report(profile, "exit_pages"); add_simple_report_element(profile, "session_page_paths", "$lang_stats.session_page_paths.label", "session_page_paths", "$lang_stats.session_page_paths.label", "session_page_paths", report_label); add_simple_report_element(profile, "session_paths", "$lang_stats.session_paths.label", "session_paths", "$lang_stats.session_paths.label", "session_paths", report_label); add_session_pages_report(profile); ); add_session_users_report(profile); add_individual_sessions_report(profile); ); # if show session report )); #### add_session_reports() #### # # add_log_detail_report() # # Purpose: This adds a log_detail report to a profile # # Parameters: profile: the profile to add the report to # subroutine(add_log_detail_report(node profile), ( string report_name = "log_detail"; string report_label = "$lang_stats." . report_name . ".label"; add_simple_report_element(profile, report_name, report_label, report_name, report_label, report_name, report_label); # Get the full report nodename node reports = profile . ".statistics.reports"; node report = reports . "." . report_name; node report_element = report . ".report_elements." . report_name; set_report_element_variable(profile, report_element, "sort_by", ""); set_report_element_variable(profile, report_element, "sort_direction", "descending"); set_report_element_variable(profile, report_element, "show_omitted_items_row", "false"); set_report_element_variable(profile, report_element, "show_totals_row", "false"); set_report_element_variable(profile, report_element, "starting_row", 0); set_report_element_variable(profile, report_element, "ending_row", 50); set_report_element_variable(profile, report_element, "show_graph", "false"); # Add database fields as columns node dbfield; foreach dbfield (profile . ".database.fields") ( string dbfieldname = node_name(dbfield); # If this is a numerical field, add it if ((node_value(subnode_by_name(dbfield, "type")) eq "int") or (node_value(subnode_by_name(dbfield, "type")) eq "float")) then ( # Don't add a column for the entries field if (node_exists(dbfield . ".entries_field") and ($(dbfield . ".entries_field"))) then ( ) else ( add_numerical_column_to_table(profile, report_element, dbfieldname, dbfield, "", false); ) ) # if numerical # If this is a non-numerical field, add it else if (node_value(subnode_by_name(dbfield, "type")) eq "string") then ( add_nonnumerical_column_to_table(profile, report_element, dbfieldname, node_name(dbfield)); ); # If the log field exists for this database field, and it's derived, hide it, # unless it's date_time (derived from date and time). string log_field_name = if (subnode_exists(dbfield, "log_field")) then node_value(subnode_by_name(dbfield, "log_field")) else node_name(dbfield); if (node_exists(profile . ".log.fields." . log_field_name)) then ( node logfield = profile . ".log.fields." . log_field_name; if ((log_field_name ne "date_time") and node_exists(logfield . ".derived_from_1")) then ( (report_element . ".columns." . dbfieldname . ".visible") = false; ); ) ); # for dbfields )); #### add_log_detail_report() #### # # add_custom_table_report_element() # # Purpose: This adds a custom table report (based on a plug-in report group node) to a profile. # # Parameters: profile: the profile # description: the node describing the report # sort_dbfield: the name of main numerical database field (the default sort field) # subroutine(add_custom_table_report_element(node profile, node description, string sort_dbfieldname), ( string report_name = node_name(description); string report_element_name = report_name; # If this is an entry or exit pages report, add it here if ((report_name eq "entry_pages") or (report_name eq "exit_pages")) then add_entry_exit_pages_report(profile, report_name); # If this is an entry or exit pages report, add it here else if (report_name eq "session_pages") then ( add_session_pages_report(profile); ); # If this is a session_users report, add it here else if (report_name eq "session_users") then ( add_session_users_report(profile); ); # If this is a individual_sessions report, add it here else if (report_name eq "individual_sessions") then ( add_individual_sessions_report(profile); ); # If it's a normal table report, add it. else ( string report_label; if (subnode_exists(description, 'label')) then report_label = node_value(subnode_by_name(description, 'label')); else if (subnode_exists(profile . ".database.fields", report_name)) then report_label = "{=capitalize(pluralize(print(database.fields." . report_name . ".label)))=}"; else if (subnode_exists('lang_stats.menu.reports', report_name)) then report_label = '$lang_stats.menu.reports.' . report_name; else if (subnode_exists('lang_stats.field_labels', report_name)) then report_label = '$lang_stats.field_labels.' . report_name; else report_label = report_name; string report_element_label = report_label; # Get the label for the menu string reports_menu_label; if (subnode_exists(description, 'reports_menu_label')) then reports_menu_label = node_value(subnode_by_name(description, 'reports_menu_label')); else reports_menu_label = report_label; debug_message("Adding custom report $report_name: '$report_label'\n"); # Get the type of the report; default to table string report_type = "table"; if (subnode_exists(description, "type")) then report_type = node_value(subnode_by_name(description, "type")); add_simple_report_element(profile, report_name, report_label, report_element_name, report_element_label, report_type, reports_menu_label); # Get the full report element nodename node reports = profile . ".statistics.reports"; node report = reports . "." . report_name; node report_element = report . ".report_elements." . report_element_name; # Add a filter if one was specified if (subnode_exists(description, 'filter')) then ( string filter = node_value(subnode_by_name(description, 'filter')); set_report_element_variable(profile, report_element, "filter.expression", filter); ); # If this is a table report, set it up. if (report_type eq "table") then ( # Default to descending sort string sort_direction = "descending"; # Set the general variables set_report_element_variable(profile, report_element, "sort_direction", sort_direction); set_report_element_variable(profile, report_element, "show_omitted_items_row", "true"); set_report_element_variable(profile, report_element, "omit_parenthesized_items", "true"); set_report_element_variable(profile, report_element, "show_totals_row", "true"); set_report_element_variable(profile, report_element, "starting_row", 1); # Set ending_row based on the report type if (report_element_name eq "day_of_week") then set_report_element_variable(profile, report_element, "ending_row", 7); else if (report_element_name eq "hour_of_day") then set_report_element_variable(profile, report_element, "ending_row", 24); else set_report_element_variable(profile, report_element, "ending_row", 10); # Default to only bottom-level items bool only_bottom_level_items = !subnode_exists(description, 'reports_menu_label') or node_value(subnode_by_name(description, 'reports_menu_label')); set_report_element_variable(profile, report_element, "only_bottom_level_items", only_bottom_level_items); # Add the non-numerical columns; use the columns node if it exists bool found_numerical_field = false; bool found_sort_field = false; string first_numerical_field_found; bool add_graph = false; int columnnum = 0; string database_field_name = "undefined"; if (subnode_exists(description, 'columns')) then ( node column; node columns = subnode_by_name(description, 'columns'); foreach column columns ( string dbfieldname = node_value(subnode_by_name(column, 'field_name')); string dbfieldnodename = profile . ".database.fields." . dbfieldname; if (node_exists(dbfieldnodename)) then ( node dbfield = dbfieldnodename; if (node_value(subnode_by_name(dbfield, 'type')) ne 'string') then ( if (!found_numerical_field) then first_numerical_field_found = dbfieldname; found_numerical_field = true; if (dbfieldname eq sort_dbfieldname) then found_sort_field = true; ); ); # if dbfield exists ); # for columns if (!found_sort_field) then sort_dbfieldname = first_numerical_field_found; # Add the non-numerical columns bool add_graph; foreach column columns ( string dbfieldname = node_value(subnode_by_name(column, 'field_name')); string dbfieldnodename = profile . ".database.fields." . dbfieldname; if (node_exists(dbfieldnodename)) then ( node dbfield = profile . ".database.fields." . dbfieldname; if (columnnum == 0) then ( set_report_element_variable(profile, report_element, "database_field_name", dbfieldname); database_field_name = dbfieldname; ); if (node_value(subnode_by_name(dbfield, 'type')) eq 'string') then add_nonnumerical_column_to_table(profile, report_element, columnnum, dbfieldname); else ( # If graph_field is specified in the description, and it's this field, show a graph add_graph = (subnode_exists(description, "graph_field") and (node_value(subnode_by_name(description, "graph_field")) eq node_name(dbfield))); add_numerical_column_to_table(profile, report_element, columnnum, dbfield, sort_dbfieldname, add_graph); ); # Put in any custom values specified in the column node node column_parameter; foreach column_parameter column ( (report_element . '.columns.' . columnnum . '.' . node_name(column_parameter)) = node_value(column_parameter); ); # Go to next column columnnum++; ); # if dbfield exists ); # for columns ); # if columns node exists # If there is no columns node, add just one non-numerical field else ( if (subnode_exists(description, 'database_field_name')) then database_field_name = node_value(subnode_by_name(description, 'database_field_name')); else if (node_exists(profile . '.database.fields.' . report_name)) then ( database_field_name = node_name(subnode_by_name(profile . ".database.fields", report_name)); ) else ( error("Cannot determine database_field_name for table report " . report_name . "\n"); ); # dbfieldname = database_field_name; set_report_element_variable(profile, report_element, "database_field_name", database_field_name); add_nonnumerical_column_to_table(profile, report_element, columnnum, database_field_name); columnnum++; ); # if no columns node # Sort by the main sort field, or by the first numerical field if the main field isn't in this table set_report_element_variable(profile, report_element, "sort_by", sort_dbfieldname); # Use subtable format if requested if (subnode_exists(description, 'subtable') and node_value(subnode_by_name(description, 'subtable'))) then ( # Add the subtable options set_report_element_variable(profile, report_element, "sub_table.ending_row", 10); set_report_element_variable(profile, report_element, "sub_table.omit_parenthesized_items", true); set_report_element_variable(profile, report_element, "sub_table.show_omitted_items_row", true); set_report_element_variable(profile, report_element, "sub_table.show_averages_row", false); set_report_element_variable(profile, report_element, "sub_table.show_totals_row", true); ); # if subtable # If no numerical fields were listed in the report, add all numerical columns if (!found_numerical_field) then ( bool add_graph; node dbfield; foreach dbfield (profile . ".database.fields") ( if (node_value(subnode_by_name(dbfield, "type")) ne "string") then ( # If this field is in the field associations list for the main database field, # or if there is no field associations list, include it in the table. if (!node_exists(profile . '.create_profile_wizard_options.database_field_associations.' . database_field_name) or node_exists(profile . '.create_profile_wizard_options.database_field_associations.' . database_field_name . '.' . node_name(dbfield))) then ( # If graph_field is specified in the description, and it's this field, show a graph add_graph = (subnode_exists(description, "graph_field") and (node_value(subnode_by_name(description, "graph_field")) eq node_name(dbfield))); debug_message("adding column '" . node_name(dbfield) . "' to '" . report_element . "'\n"); add_numerical_column_to_table(profile, report_element, columnnum, dbfield, sort_dbfieldname, add_graph); columnnum++; ); # if field associated else ( debug_message("NOT adding column '" . node_name(dbfield) . "' to '" . report_element . "'\n"); # If this is the sort field, and it's not being put in the table, then we need to sort by something else; # use the first field if (node_name(dbfield) eq sort_dbfieldname) then ( debug_message(" ... Uh oh, that's the default sort field; we need to find another field to sort on.\n"); sort_dbfieldname = node_name(subnode_by_number(profile . '.create_profile_wizard_options.database_field_associations.' . database_field_name, 0)); set_report_element_variable(profile, report_element, "sort_by", sort_dbfieldname); debug_message(" ... sorting on '" . sort_dbfieldname . "'\n"); ); # if sort field ); # if field not associated ); # if numerical ); # for dbfields ); # if no numerical fields listed ); # if table report ); # if normal table report # Copy the description parameter values to the report node description_parameter; node reports = profile . ".statistics.reports"; node report = reports . "." . report_name; node report_element = report . ".report_elements." . report_element_name; foreach description_parameter description ( string description_parameter_name = node_name(description_parameter); if ((node_name(description_parameter) ne "columns") and (node_name(description_parameter) ne "filter") and (node_name(description_parameter) ne "graph_field")) then ( # string description_parameter_value = node_value(description_parameter); string report_element_parameter_nodepath = report_element . "." . node_name(description_parameter); clone_node(description_parameter, report_element_parameter_nodepath); # set_subnode_value(report_element, description_parameter_name, description_parameter_value); debug_message(" Set parameter " . description_parameter_name . "=" . node_as_string(description_parameter) . "\n"); ); ); # foreach description_parameter )); #### add_custom_table_report_element() #### # # add_single_page_summary() # # Purpose: This adds a single page summary report to a profile # # Parameters: profile: the profile to add the report to # subroutine(add_single_page_summary(node profile), ( string report_name = "single_page_summary"; # Add the single-page summary report and overview string report_label = "$lang_stats.single_page_summary.label"; string report_element_label = "$lang_stats.overview.label"; add_simple_report_element(profile, report_name, report_label, "overview", report_element_label, "overview", report_label); node reports = profile . ".statistics.reports"; node report; foreach report (reports) ( string report_name = node_name(report); if (report_name ne "single_page_summary") then ( node report_elements = subnode_by_name(report, 'report_elements'); node report_element = subnode_by_number(report_elements, 0); string report_element_type = node_value(subnode_by_name(report_element, 'type')); if ((report_element_type eq 'session_paths') or (report_element_type eq 'session_page_paths') or (report_element_type eq 'individual_sessions') or (report_element_type eq 'log_detail')) then () else ( string report_element_name = node_name(report_element); string sss_report_element_path = reports . ".single_page_summary.report_elements." . report_element_name; clone_node(report_element, sss_report_element_path); (sss_report_element_path . ".show_header_bar") = true; # debug_message("Cloned report '" . report_element_name . "' to single-page summary\n"); # debug_message("Cloned report: " . node_as_string(report_element) . "\n"); ); ); ); #debug_message("Now single-page summary: " . node_as_string(reports . ".single_page_summary") . "\n"); )); #### add_single_page_summary() #### # # clean_up_log_filters() # # Purpose: This cleans the log filters, removing any that refer to fields that don't exist. # # Parameters: profile: the profile to clean # subroutine(clean_up_log_filters(node profile), ( # Clean up filters and parsing filters for (int type = 0; type < 2; type++) ( string filters; if (type == 0) then filters = profile . ".log.filters"; else filters = profile . ".log.parsing_filters"; # Look through all the filters int num_filters = num_subnodes(filters); int filter_num; for (filter_num = 0; filter_num < num_filters; filter_num++) ( node filter = subnode_by_number(filters, filter_num); string filter_value = node_value(filter); # Do special cleanup on log.filters if (type == 0) then ( # If this is a final events filter (with any field name) but events are not being tracked, delete it # This is a general version of the two filters below; it will work with any field name. if (matches_regular_expression(filter_value, "^([a-z_]+) = 1;") and !node_exists(profile . ".log.fields." . $1)) then ( delete_node(filter); filter_num = -1; ); # If this is a final requests filter but requests are not being tracked, delete it if (contains(filter_value, "requests = 1;") and !node_exists(profile . ".log.fields.requests")) then ( delete_node(filter); filter_num = -1; ); # If this is a file type categorization filter but page views is not being tracked, delete it if (contains(filter_value, "file_type eq 'GIF'") and !node_exists(profile . ".log.fields.page_views")) then ( delete_node(filter); filter_num = -1; ); # If this is a filter that looks for page_views == 0 but page views is not being tracked, delete it if (contains(filter_value, "page_views == 0") and !node_exists(profile . ".log.fields.page_views")) then ( delete_node(filter); filter_num = -1; ); ); # if log.filters # If this filter contains a requires_fields node, make sure all the fields it needs exist; otherwise, delete it. if (node_exists(filter . ".requires_fields")) then ( node required_field; bool delete_filter = false; foreach required_field (filter . ".requires_fields") ( if (!node_exists(profile . ".log.fields." . node_name(required_field))) then ( delete_filter = true; ); ); if (delete_filter) then ( delete_node(filter); filter_num = -1; ); ); int num_filters = num_subnodes(filters); ); # for filter_num ); # for filter type )); #### clean_up_log_filters() #### # # delete_database_field() # # Purpose: This deletes a database field # # Parameters: profile: the profile # dbfieldname: the name of the field to delete # subroutine(delete_database_field(node profile, string dbfieldname), ( # Make sure the field exists if (node_exists(profile . ".database.fields." . dbfieldname)) then ( delete_node(profile . ".database.fields." . dbfieldname); node group; foreach group (profile . ".database.cross_reference_groups") ( bool detected_field = false; node field; foreach field group ( if (node_name(field) eq dbfieldname) then ( detected_field = true; ); ); # foreach field # If this group contained the field, delete it if (detected_field) then ( delete_node(group); ); ); # foreach group ); # if field exists )); #### delete_database_field() #### # # delete_xref_group() # # Purpose: This deletes a cross-reference group # # Parameters: profile: the profile # xrefgroup: the name of the group to delete # subroutine(delete_xref_group(node profile, string xrefgroup), ( # Make sure the group exists if (node_exists(profile . ".database.cross_reference_groups." . xrefgroup)) then ( delete_node(profile . ".database.cross_reference_groups." . xrefgroup); ); # if group exists )); #### delete_xref_group() #### # # add_field_to_xref_group() # # Purpose: This adds a field to a cross-reference group # # Parameters: profile: the profile # xrefgroupname: the name of the group to add to # dbfieldname: the name of the field to add # subroutine(add_field_to_xref_group(node profile, string xrefgroupname, string dbfieldname), ( # Add this field, if it exists if (node_exists(profile . ".database.fields." . dbfieldname)) then (profile . ".database.cross_reference_groups." . xrefgroupname . "." . dbfieldname) = ""; )); #### add_field_to_xref_group() #### # # add_standard_reports() # # Purpose: This adds all standard reports to a profile # # Parameters: profile: the profile to add the report to # subroutine(add_standard_reports(node profile), ( # Add labels to any database fields that don't have them node dbfield; foreach dbfield (profile . ".database.fields") ( if (!subnode_exists(dbfield, "label")) then ( # if (subnode_exists(dbfield, 'aggregation_method') and (node_value(subnode_by_name(dbfield, 'aggregation_method')) eq 'average')) then # (dbfield . ".label") .= " $lang_stats.field_labels.average_tag"; if (node_exists("lang_stats.field_labels." . node_name(dbfield))) then ( (dbfield . ".label") = "$lang_stats.field_labels." . node_name(dbfield); debug_message("defaulting dbfield label for " . node_name(dbfield) . " to '" . $(dbfield . ".label") . "'\n"); ); else if (node_exists(profile . ".log.fields." . node_name(dbfield) . ".label")) then ( (dbfield . ".label") = node_value(profile . ".log.fields." . node_name(dbfield) . ".label"); debug_message("getting dbfield label for " . node_name(dbfield) . " from log field label '" . $(dbfield . ".label") . "'\n"); ); else ( if (!node_exists('v.found_undefined_field')) then ( debug_message("####\n"); debug_message("#### WARNING: lang_stats.field_labels." . node_name(dbfield) . " not found\n"); debug_message("#### using node name (" . node_name(dbfield) . ") as label.\n"); debug_message("#### Suggestions for lang_stats entries for this and any other undefined fields:\n"); debug_message("####\n"); v.found_undefined_field = true; ); debug_message(" " . node_name(dbfield) . " = \"" . replace_all(node_name(dbfield), '_', ' ') . "\"\n"); (dbfield . ".label") = node_name(dbfield); ) ); # if there is no log_field specified, assume the log field is the same as the database field if (!subnode_exists(dbfield, "log_field")) then (dbfield . ".log_field") = node_name(dbfield); # If there is no type field specified, default to "string" if (!subnode_exists(dbfield, "type")) then (dbfield . ".type") = "string"; # Set default suppress_top and suppress_bottom if (!subnode_exists(dbfield, "suppress_top")) then (dbfield . ".suppress_top") = "0"; if (!subnode_exists(dbfield, "suppress_bottom")) then ( if (node_name(dbfield) eq "date_time") then (dbfield . ".suppress_bottom") = "3"; else (dbfield . ".suppress_bottom") = "2"; ); ); # for database fields # Set default display format type for certain fields if (node_exists(profile . ".database.fields.date_time") and !node_exists(profile . ".database.fields.date_time.display_format_type")) then (profile . ".database.fields.date_time.display_format_type") = "date_time"; if (node_exists(profile . ".database.fields.day_of_week") and !node_exists(profile . ".database.fields.day_of_week.display_format_type")) then (profile . ".database.fields.day_of_week.display_format_type") = "day_of_week"; if (node_exists(profile . ".database.fields.hour_of_day") and !node_exists(profile . ".database.fields.hour_of_day.display_format_type")) then (profile . ".database.fields.hour_of_day.display_format_type") = "hour_of_day"; # If there is no type specified for a log field, default to "flat" node logfield; foreach logfield (profile . ".log.fields") ( if (!subnode_exists(logfield, "type")) then ( if (node_name(logfield) eq "date") then (logfield . ".type") = "date"; else if (node_name(logfield) eq "time") then (logfield . ".type") = "time"; else (logfield . ".type") = "flat"; ); # Use lang_stats.field_labels for label if none exists if (!subnode_exists(logfield, "label")) then ( if (node_exists("lang_stats.field_labels." . node_name(logfield))) then ( (logfield . ".label") = "$lang_stats.field_labels." . node_name(logfield); ) # If lang_stats.field_labels value doesn't exist, use node name else ( if (!node_exists('v.found_undefined_field')) then ( debug_message("####\n"); debug_message("#### WARNING: lang_stats.field_labels." . node_name(logfield) . " not found\n"); debug_message("#### using node name (" . node_name(dbfield) . ") as label.\n"); debug_message("#### Suggestions for lang_stats entries for this and any other undefined fields:\n"); debug_message("####\n"); v.found_undefined_field = true; ); debug_message(" " . node_name(logfield) . " = \"" . replace_all(node_name(logfield), '_', ' ') . "\"\n"); (logfield . ".label") = node_name(logfield); ) ); ); # for log fields # Clear all reports # delete_node(profile . ".statistics.reports"); # delete_node(profile . ".statistics.reports_menu"); # If there is a report_groups node in the plug-in, use it node report_groups; if (node_exists(profile . ".create_profile_wizard_options.report_groups")) then ( report_groups = (profile . ".create_profile_wizard_options.report_groups"); ) # Otherwise, use the default report groups node else ( report_groups = "templates.admin.profiles.report_groups"; ); # Find the first numerical field string main_numerical_dbfield; foreach dbfield (profile . ".database.fields") ( if ($(dbfield . ".type") ne "string") then ( main_numerical_dbfield = node_name(dbfield); last; ) # if ($(dbfield . ".type") ne "string") then # main_numerical_dbfield = node_name(dbfield); ); # Check if the reports menu is manually specified; if not, create an automatic menu if (!node_exists(profile . ".create_profile_wizard_options.manual_reports_menu") or !node_value(profile . ".create_profile_wizard_options.manual_reports_menu")) then ( # Add stub nodes for all groups and reports, so they appear in the order we want node group; (profile . ".statistics.reports_menu.overview.type") = "uninitialized"; foreach group report_groups ( string group_name = node_name(group); string group_node = profile . ".statistics.reports_menu." . group_name; # If this group or report doesn't exist, create it minimally with just a type node if (!node_exists(group_node) and ((num_subnodes(group) > 0) or (node_value(group) ne "false"))) then ( (group_node . ".type") = "uninitialized"; ); ); # foreach group # Add the Overview string report_name = "overview"; string report_label = "$lang_stats.overview.label"; debug_message("ADDING OVERVIEW\n"); add_simple_report_element(profile, report_name, report_label, report_name, report_label, report_name, report_label); # Add a table report for each non-numerical database field node dbfield; foreach dbfield (profile . ".database.fields") ( # If this is non-numerical, add a table for it if (node_value(subnode_by_name(dbfield, "type")) eq "string") then ( string dbfieldname = node_name(dbfield); # Don't create this report if there is a custom one for this field if (node_exists(report_groups . "." . dbfieldname . ".label")) then ( debug_message("Not creating standard report for " . dbfieldname . " because there is a custom one\n"); next; ); string log_field_name = if (subnode_exists(dbfield, "log_field")) then node_value(subnode_by_name(dbfield, "log_field")) else node_name(dbfield); # Get the log field type. If there's no log field matching, handle known derived fields string log_field_type; if (node_exists(profile . ".log.fields." . log_field_name . ".type")) then log_field_type = $(profile . ".log.fields." . log_field_name . ".type"); else if (log_field_name eq "date_time") then log_field_type = "date_time"; else log_field_type = "flat"; # Get the label for the hierarchical report string report_label; if (log_field_type eq "page") then ( report_label = "{=capitalize(pluralize(print(database.fields." . dbfieldname . ".label))) . '/' . lang_stats.miscellaneous.directories;=}"; ) else if (log_field_type eq "date_time") then ( report_label = "$lang_stats.miscellaneous.years_months_days"; ); else ( report_label = "{=capitalize(pluralize(print(database.fields." . dbfieldname . ".label)))=}"; ); # Compute the sort order and direction string sort_order; string sort_direction; if ((dbfieldname eq "date_time") or (dbfieldname eq "day_of_week") or (dbfieldname eq "hour_of_day")) then ( sort_order = dbfieldname; sort_direction = "ascending"; ) else ( sort_order = main_numerical_dbfield; sort_direction = "descending"; ); # Add a hierarchical report for this field add_table_report_element(profile, dbfieldname, report_label, dbfieldname, report_label, dbfieldname, "", main_numerical_dbfield, sort_order, sort_direction, false); # If this is the date/time field, add a "days" report also if (log_field_type eq "date_time") then add_table_report_element(profile, "days", "$lang_stats.miscellaneous.days", "days", "$lang_stats.miscellaneous.days", dbfieldname, "", main_numerical_dbfield, dbfieldname, sort_direction, true); # If this is the page field, add a "pages" report also if (log_field_type eq "page") then add_table_report_element(profile, dbfieldname . "_bottom_level_items", "{=pluralize(capitalize(print(database.fields." . dbfieldname . ".label)));=}", dbfieldname . "_bottom_level_items", "{=pluralize(capitalize(print(database.fields." . dbfieldname . ".label)));=}", dbfieldname, "", main_numerical_dbfield, main_numerical_dbfield, sort_direction, true); ); # if string field ); # foreach dbfield # Add search engines by search phrases, if both fields exists # if (node_exists(profile . ".database.fields.search_engine") and node_exists(profile . ".database.fields.search_phrase")) then # add_table_report_element(profile, "search_phrases_by_search_engine", "$lang_stats.search_phrases_by_search_engine.label", "search_phrases_by_search_engine", "$lang_stats.search_phrases_by_search_engine.label", "search_engine", "search_phrase", main_numerical_dbfield, main_numerical_dbfield, "descending", false); # ); # if not manual # Add any X_by_Y reports listed in report_groups foreach group report_groups ( # string group_name = node_name(group); # If there is a "label" node, this must be a custom report; build it if (subnode_exists(group, 'label')) then ( add_custom_table_report_element(profile, group, main_numerical_dbfield); ); # Otherwise, it must be a group else ( node report; foreach report group ( string report_name = node_name(report); if (matches_regular_expression(report_name, '^(.*)_by_(.*)$')) then ( string dbfieldname1 = $1; string dbfieldname2 = $2; if (node_exists(profile . ".database.fields." . dbfieldname1) and node_exists(profile . ".database.fields." . dbfieldname2)) then ( debug_message("Adding '" . dbfieldname1 . " by " . dbfieldname2 . "' report\n"); string report_label = "{=capitalize(print(database.fields." . dbfieldname1 . ".label)) . lang_stats.multi_column_report_divider . database.fields." . dbfieldname2 . ".label=}"; add_table_report_element(profile, report_name, report_label, report_name, report_label, dbfieldname2, dbfieldname1, main_numerical_dbfield, main_numerical_dbfield, "descending", false); ); ); # If there is a "label" node, this must be a custom report; build it else if (subnode_exists(report, 'label')) then ( add_custom_table_report_element(profile, report, main_numerical_dbfield); ); # if custom report ); # foreach report ); # if group ); # foreach group # Add all standard session reports add_session_reports(profile); # Add the single-page summary add_single_page_summary(profile); # Add the log detail report add_log_detail_report(profile); # Delete any groups or reports that weren't added node group; bool deleted = true; while (deleted) ( # Look for one with type "uninitialized" -- if we find one, delete it deleted = false; foreach group report_groups ( string group_name = node_name(group); string group_node = profile . ".statistics.reports_menu." . group_name; # If this is is "uninitialized", delete it and start again if (node_exists(group_node) and ($(group_node . ".type") eq "uninitialized")) then ( deleted = true; delete_node(group_node); last; ); ); # foreach group ); # foreach group ); # if automatic report menu generation # Otherwise, generate the reports as specified manually in report_groups else ( # Loop through all groups node group; foreach group report_groups ( string group_name = node_name(group); # If this is the single page summary, add it here if (group_name eq "single_page_summary") then add_single_page_summary(profile); # If this is the log detail report, add it here else if (group_name eq "log_detail") then add_log_detail_report(profile); # If this is a normal report, create it else ( # Create the report menu group (profile . ".statistics.reports_menu." . node_name(group)) = ""; node reports_menu_group_node = (profile . ".statistics.reports_menu." . node_name(group)); set_subnode_value(reports_menu_group_node, "type", "group"); string group_label; if (subnode_exists(group, 'label')) then group_label = node_value(subnode_by_name(group, 'label')); else if (node_exists("lang_stats.menu.groups." . node_name(group))) then group_label = "$lang_stats.menu.groups." . node_name(group); else group_label = node_name(group); set_subnode_value(reports_menu_group_node, "label", group_label); # If there is a "items" node, this must be a group if (subnode_exists(group, 'items')) then ( set_subnode_value(reports_menu_group_node, "items", ""); node reports_menu_items_node = subnode_by_name(reports_menu_group_node, "items"); node item; node items = subnode_by_name(group, 'items'); foreach item items ( string report_name = node_name(item); set_subnode_value(reports_menu_items_node, report_name, ""); add_custom_table_report_element(profile, item, main_numerical_dbfield); ); # foreach item ); # if group # Otherwise, it must be a report; add it else ( string report_name = node_name(group); add_custom_table_report_element(profile, group, main_numerical_dbfield); ); ); # if not sss or log_detail ); # foreach group ); # if manual report menu # Clean up log filters, removing any that don't belong. clean_up_log_filters(profile); )); #### add_standard_reports() ####