delete_database_field = { label = "Delete Database Field" shortcut = "ddf" requires_profile = true parameters = { database_field_name = { label = "Database field name" description = "The internal name of the database field to delete" shortcut = "dfn" required = true } } expression = ` string dbfieldname = database_field_name; # Get the profile node node profile = "profiles." . internal.profile_name; # Get the nodes within the profile we'll be using node database_fields = profile{"database"}{"fields"}; node report_fields = profile{"statistics"}{"report_fields"}; node reports = profile{"statistics"}{"reports"}; node reports_menu = profile{"statistics"}{"reports_menu"}; node cross_reference_groups = profile{"database"}{"cross_reference_groups"}; node field_options = profile{"log"}{"field_options"}; # Check for session fields; this action isn't smart enough to deal with deleting session fields if (false or (@field_options{"sessions_visitor_id_field"} eq dbfieldname) or (@field_options{"sessions_event_field"} eq dbfieldname) or (@field_options{"sessions_page_field"} eq dbfieldname) or (@field_options{"sessions_id_field"} eq dbfieldname) or false) then ( error("Database field '" . dbfieldname . "' is a session field, which is not supported by this action"); ); if (!database_fields?{dbfieldname}) then ( error("Database field '" . dbfieldname . "' does not exist"); ); # # delete_from_reports_menu() # # Purpose: This subroutine deletes all references to a particular report from the reports menu, or a submenu of it. # # Parameters: report_name: the name of the deleted report # reports_menu_node: the reports menu node to examine # subroutine(delete_from_reports_menu(string report_name, node reports_menu_node), ( # Iterate through all subnodes int itemnum = 0; while (itemnum < num_subnodes(reports_menu_node)) ( node reports_menu_subnode = reports_menu_node[itemnum]; # If this has "items", it must be a group node; process it recursively, and go to next node if (reports_menu_subnode?{"items"}) then ( delete_from_reports_menu(report_name, reports_menu_subnode{"items"}); itemnum++; ); # If the report referred to by this node is the report just deleted, delete this node else if (reports_menu_subnode?{"report"} and (@reports_menu_subnode{"report"} eq report_name)) then ( echo("Deleting report menu item '" . expand(@reports_menu_subnode{"label"}) . "' (" . reports_menu_subnode . ") because it refers to report '" . report_name . "', which has been deleted"); delete_node(reports_menu_subnode); ); # Go to next node. else itemnum++; ); # while itemnum )); #### delete_from_reports_menu() #### ## ## DELETE FIELD FROM REPORTS ## # Iterate through all reports int report_number = 0; while (report_number < num_subnodes(reports)) ( node report = reports[report_number]; # Iterate through all report elements of this report node report_elements = report{"report_elements"}; int report_element_number = 0; while (report_element_number < num_subnodes(report_elements)) ( node report_element = report_elements[report_element_number]; # If this has columns, iterate through all columns bool delete_this_report_element = false; if (report_element?{"columns"}) then ( node columns = report_element{"columns"}; int colnum = 0; bool found_nonaggregating_field = false; while (colnum < num_subnodes(columns)) ( node column = columns[colnum]; node report_field = report_fields{@column{"report_field"}}; node dbfield = database_fields{@report_field{"database_field"}}; # If this column's report field matches the field we're deleting, delete this column # 2011-12-19 - GMF - Changed this to use the database_field from the report field; otherwise it won't delete the "city" column if you delete the "location" database field. # if (@column{"report_field"} eq dbfieldname) then ( if (@report_field{"database_field"} eq dbfieldname) then ( echo("Deleting column " . colnum . " of report element '" . expand(@report_element{"label"}) . "' of report '" . expand(@report{"label"}) . "' because it is report field '" . @column{"report_field"} . "', which is based on database field " . dbfieldname); delete_node(column); ); # Otherwise, go to the next column. else ( colnum++; # If this field is non-aggregating, remember that we found a non-aggregating field if (@dbfield{"aggregation_method"} eq "none") then found_nonaggregating_field = true; ); # if report field is not dbfieldname ); # while columns # If we didn't find any non-aggregating fields, we should delete thie report element below if (!found_nonaggregating_field) then ( # 2011-12-19 - GMF - But, don't delete the Overview; it never has any non-aggregating fields! if (@report_element{"type"} ne "overview") then delete_this_report_element = true; ); ); # if columns # If there are no non-aggregating fields left, delete the report element if (delete_this_report_element) then ( echo("Deleting report element '" . expand(@report_element{"label"}) . "' because it no longer has any non-aggregating fields"); delete_node(report_element); ); # Otheriwse, to to the next report element else report_element_number++; ); # while report_element_number # If this report now has no elements, delete it if (num_subnodes(report_elements) == 0) then ( # Delete it from the reports menu, if it's there delete_from_reports_menu(node_name(report), reports_menu); echo("Deleting report '" . expand(@report{"label"}) . "' because it no longer has any elements"); delete_node(report); ); # if report has no elements # If the report still has elements, leave it, and go to the next report else report_number++; ); # while report_number ## ## DELETE FIELD FROM XREFS ## # Iterate through all xref groups int xref_group_number = 0; while (xref_group_number < num_subnodes(cross_reference_groups)) ( node xref_group = cross_reference_groups[xref_group_number]; # Iterate through all fields of the xref group node fields = xref_group{"fields"}; int fieldnum = 0; bool found_nonaggregating_field = false; while (fieldnum < num_subnodes(fields)) ( node field = fields[fieldnum]; node dbfield = database_fields{node_name(field)}; # If this field is the one we're deleting, delete it from the xref group if (node_name(field) eq dbfieldname) then ( echo("Deleting field " . fieldnum . " (database field '" . node_name(field) . "') of cross-reference group '" . expand(@xref_group{"label"})); delete_node(field); ); # Otherwise, go to the next field else ( fieldnum++; # If this is a non-aggregating, remember that we found one. if ((@dbfield{"aggregation_method"} eq "none") and (node_name(dbfield) ne "date_time")) then found_nonaggregating_field = true; ); # if database field is not dbfieldname ); # while fields # If there are no non-aggregating fields left (except perhaps date_time), delete this xref if (!found_nonaggregating_field) then ( echo("Deleting cross-reference group '" . expand(@xref_group{"label"}) . "' because it no longer has any non-date/time non-aggregating fields"); delete_node(xref_group); ); # Otherwise, go to the next group else xref_group_number++; ); # while xref_group_number ## ## DELETE REPORT FIELDS ## # Iterate through all report fields int reportfieldnum = 0; while (reportfieldnum < num_subnodes(report_fields)) ( node report_field = report_fields[reportfieldnum]; # If this report field uses the database field we just deleted, delete this report field if (@report_field{"database_field"} eq dbfieldname) then ( echo("Deleting report field '" . expand(@report_field{"label"}) . "' because it is based on the database field '" . dbfieldname . "'"); delete_node(report_field); ); # Otherwise, continue to the next report field else reportfieldnum++; ); # while reportfieldnum ## ## DELETE THE DATABASE FIELD ## # If the database field exists, delete it if (database_fields?{dbfieldname}) then ( node dbfield = database_fields{dbfieldname}; echo("Deleting database field '" . expand(@dbfield{"label"}) . "'"); delete_node(dbfield); ); # Write the modified profile to disk save_node(profile); echo("Saved modified profile '" . @profile{"label"} . "'"); ` # expression } # delete_database_field