mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-12 23:14:18 +01:00
Merge remote-tracking branch 'origin/develop' into feature/backoffice-full-moon-design
# Conflicts: # webservices/import.php
This commit is contained in:
525
.editorconfig
525
.editorconfig
@@ -13,7 +13,7 @@ ij_formatter_off_tag = @formatter:off
|
||||
ij_formatter_on_tag = @formatter:on
|
||||
ij_formatter_tags_enabled = false
|
||||
ij_smart_tabs = false
|
||||
ij_visual_guides = 140
|
||||
ij_visual_guides = 80,120
|
||||
ij_wrap_on_typing = true
|
||||
|
||||
[*.css]
|
||||
@@ -22,7 +22,8 @@ ij_smart_tabs = true
|
||||
ij_css_align_closing_brace_with_properties = false
|
||||
ij_css_blank_lines_around_nested_selector = 1
|
||||
ij_css_blank_lines_between_blocks = 1
|
||||
ij_css_brace_placement = 0
|
||||
ij_css_brace_placement = end_of_line
|
||||
ij_css_enforce_quotes_on_format = false
|
||||
ij_css_hex_color_long_format = false
|
||||
ij_css_hex_color_lower_case = false
|
||||
ij_css_hex_color_short_format = false
|
||||
@@ -33,15 +34,16 @@ ij_css_keep_single_line_blocks = false
|
||||
ij_css_properties_order = font,font-family,font-size,font-weight,font-style,font-variant,font-size-adjust,font-stretch,line-height,position,z-index,top,right,bottom,left,display,visibility,float,clear,overflow,overflow-x,overflow-y,clip,zoom,align-content,align-items,align-self,flex,flex-flow,flex-basis,flex-direction,flex-grow,flex-shrink,flex-wrap,justify-content,order,box-sizing,width,min-width,max-width,height,min-height,max-height,margin,margin-top,margin-right,margin-bottom,margin-left,padding,padding-top,padding-right,padding-bottom,padding-left,table-layout,empty-cells,caption-side,border-spacing,border-collapse,list-style,list-style-position,list-style-type,list-style-image,content,quotes,counter-reset,counter-increment,resize,cursor,user-select,nav-index,nav-up,nav-right,nav-down,nav-left,transition,transition-delay,transition-timing-function,transition-duration,transition-property,transform,transform-origin,animation,animation-name,animation-duration,animation-play-state,animation-timing-function,animation-delay,animation-iteration-count,animation-direction,text-align,text-align-last,vertical-align,white-space,text-decoration,text-emphasis,text-emphasis-color,text-emphasis-style,text-emphasis-position,text-indent,text-justify,letter-spacing,word-spacing,text-outline,text-transform,text-wrap,text-overflow,text-overflow-ellipsis,text-overflow-mode,word-wrap,word-break,tab-size,hyphens,pointer-events,opacity,color,border,border-width,border-style,border-color,border-top,border-top-width,border-top-style,border-top-color,border-right,border-right-width,border-right-style,border-right-color,border-bottom,border-bottom-width,border-bottom-style,border-bottom-color,border-left,border-left-width,border-left-style,border-left-color,border-radius,border-top-left-radius,border-top-right-radius,border-bottom-right-radius,border-bottom-left-radius,border-image,border-image-source,border-image-slice,border-image-width,border-image-outset,border-image-repeat,outline,outline-width,outline-style,outline-color,outline-offset,background,background-color,background-image,background-repeat,background-attachment,background-position,background-position-x,background-position-y,background-clip,background-origin,background-size,box-decoration-break,box-shadow,text-shadow
|
||||
ij_css_space_after_colon = true
|
||||
ij_css_space_before_opening_brace = true
|
||||
ij_css_value_alignment = 0
|
||||
ij_css_use_double_quotes = true
|
||||
ij_css_value_alignment = do_not_align
|
||||
|
||||
[*.scss]
|
||||
indent_style = tab
|
||||
ij_smart_tabs = true
|
||||
ij_scss_align_closing_brace_with_properties = false
|
||||
ij_scss_blank_lines_around_nested_selector = 1
|
||||
ij_scss_blank_lines_between_blocks = 1
|
||||
ij_scss_brace_placement = 0
|
||||
ij_scss_enforce_quotes_on_format = false
|
||||
ij_scss_hex_color_long_format = false
|
||||
ij_scss_hex_color_lower_case = false
|
||||
ij_scss_hex_color_short_format = false
|
||||
@@ -52,12 +54,15 @@ ij_scss_keep_single_line_blocks = false
|
||||
ij_scss_properties_order = font,font-family,font-size,font-weight,font-style,font-variant,font-size-adjust,font-stretch,line-height,position,z-index,top,right,bottom,left,display,visibility,float,clear,overflow,overflow-x,overflow-y,clip,zoom,align-content,align-items,align-self,flex,flex-flow,flex-basis,flex-direction,flex-grow,flex-shrink,flex-wrap,justify-content,order,box-sizing,width,min-width,max-width,height,min-height,max-height,margin,margin-top,margin-right,margin-bottom,margin-left,padding,padding-top,padding-right,padding-bottom,padding-left,table-layout,empty-cells,caption-side,border-spacing,border-collapse,list-style,list-style-position,list-style-type,list-style-image,content,quotes,counter-reset,counter-increment,resize,cursor,user-select,nav-index,nav-up,nav-right,nav-down,nav-left,transition,transition-delay,transition-timing-function,transition-duration,transition-property,transform,transform-origin,animation,animation-name,animation-duration,animation-play-state,animation-timing-function,animation-delay,animation-iteration-count,animation-direction,text-align,text-align-last,vertical-align,white-space,text-decoration,text-emphasis,text-emphasis-color,text-emphasis-style,text-emphasis-position,text-indent,text-justify,letter-spacing,word-spacing,text-outline,text-transform,text-wrap,text-overflow,text-overflow-ellipsis,text-overflow-mode,word-wrap,word-break,tab-size,hyphens,pointer-events,opacity,color,border,border-width,border-style,border-color,border-top,border-top-width,border-top-style,border-top-color,border-right,border-right-width,border-right-style,border-right-color,border-bottom,border-bottom-width,border-bottom-style,border-bottom-color,border-left,border-left-width,border-left-style,border-left-color,border-radius,border-top-left-radius,border-top-right-radius,border-bottom-right-radius,border-bottom-left-radius,border-image,border-image-source,border-image-slice,border-image-width,border-image-outset,border-image-repeat,outline,outline-width,outline-style,outline-color,outline-offset,background,background-color,background-image,background-repeat,background-attachment,background-position,background-position-x,background-position-y,background-clip,background-origin,background-size,box-decoration-break,box-shadow,text-shadow
|
||||
ij_scss_space_after_colon = true
|
||||
ij_scss_space_before_opening_brace = true
|
||||
ij_scss_use_double_quotes = true
|
||||
ij_scss_value_alignment = 0
|
||||
|
||||
[*.twig]
|
||||
indent_style = tab
|
||||
ij_smart_tabs = true
|
||||
ij_wrap_on_typing = false
|
||||
ij_twig_keep_indents_on_empty_lines = false
|
||||
ij_twig_spaces_inside_comments_delimiters = true
|
||||
ij_twig_spaces_inside_delimiters = true
|
||||
ij_twig_spaces_inside_variable_delimiters = true
|
||||
|
||||
@@ -69,212 +74,37 @@ ij_editorconfig_space_before_colon = false
|
||||
ij_editorconfig_space_before_comma = false
|
||||
ij_editorconfig_spaces_around_assignment_operators = true
|
||||
|
||||
[{*.ctp,*.phtml,*.module,*.php,*.php5,*.php4,*.hphp,*.inc}]
|
||||
indent_style = tab
|
||||
ij_continuation_indent_size = 4
|
||||
[{*.ant,*.fxml,*.jhm,*.jnlp,*.jrxml,*.rng,*.tld,*.wsdl,*.xml,*.xsd,*.xsl,*.xslt,*.xul,phpunit.xml.dist}]
|
||||
indent_size = 2
|
||||
tab_width = 2
|
||||
ij_smart_tabs = true
|
||||
ij_wrap_on_typing = false
|
||||
ij_php_align_assignments = false
|
||||
ij_php_align_class_constants = false
|
||||
ij_php_align_group_field_declarations = false
|
||||
ij_php_align_inline_comments = false
|
||||
ij_php_align_key_value_pairs = false
|
||||
ij_php_align_multiline_array_initializer_expression = false
|
||||
ij_php_align_multiline_binary_operation = false
|
||||
ij_php_align_multiline_chained_methods = false
|
||||
ij_php_align_multiline_extends_list = false
|
||||
ij_php_align_multiline_for = true
|
||||
ij_php_align_multiline_parameters = false
|
||||
ij_php_align_multiline_parameters_in_calls = false
|
||||
ij_php_align_multiline_ternary_operation = false
|
||||
ij_php_align_phpdoc_comments = false
|
||||
ij_php_align_phpdoc_param_names = false
|
||||
ij_php_api_weight = 1
|
||||
ij_php_array_initializer_new_line_after_left_brace = true
|
||||
ij_php_array_initializer_right_brace_on_new_line = true
|
||||
ij_php_array_initializer_wrap = on_every_item
|
||||
ij_php_assignment_wrap = off
|
||||
ij_php_author_weight = 7
|
||||
ij_php_binary_operation_sign_on_next_line = false
|
||||
ij_php_binary_operation_wrap = off
|
||||
ij_php_blank_lines_after_class_header = 0
|
||||
ij_php_blank_lines_after_function = 1
|
||||
ij_php_blank_lines_after_imports = 1
|
||||
ij_php_blank_lines_after_opening_tag = 0
|
||||
ij_php_blank_lines_after_package = 1
|
||||
ij_php_blank_lines_around_class = 1
|
||||
ij_php_blank_lines_around_constants = 0
|
||||
ij_php_blank_lines_around_field = 0
|
||||
ij_php_blank_lines_around_method = 1
|
||||
ij_php_blank_lines_before_class_end = 0
|
||||
ij_php_blank_lines_before_imports = 1
|
||||
ij_php_blank_lines_before_method_body = 0
|
||||
ij_php_blank_lines_before_package = 1
|
||||
ij_php_blank_lines_before_return_statement = 1
|
||||
ij_php_block_brace_style = end_of_line
|
||||
ij_php_call_parameters_new_line_after_left_paren = false
|
||||
ij_php_call_parameters_right_paren_on_new_line = false
|
||||
ij_php_call_parameters_wrap = normal
|
||||
ij_php_catch_on_new_line = false
|
||||
ij_php_category_weight = 28
|
||||
ij_php_class_brace_style = end_of_line
|
||||
ij_php_comma_after_last_array_element = true
|
||||
ij_php_concat_spaces = false
|
||||
ij_php_copyright_weight = 28
|
||||
ij_php_deprecated_weight = 28
|
||||
ij_php_do_while_brace_force = always
|
||||
ij_php_else_if_style = as_is
|
||||
ij_php_else_on_new_line = true
|
||||
ij_php_example_weight = 3
|
||||
ij_php_extends_keyword_wrap = off
|
||||
ij_php_extends_list_wrap = off
|
||||
ij_php_fields_default_visibility = private
|
||||
ij_php_filesource_weight = 28
|
||||
ij_php_finally_on_new_line = false
|
||||
ij_php_for_brace_force = always
|
||||
ij_php_for_statement_new_line_after_left_paren = false
|
||||
ij_php_for_statement_right_paren_on_new_line = false
|
||||
ij_php_for_statement_wrap = off
|
||||
ij_php_force_short_declaration_array_style = false
|
||||
ij_php_global_weight = 28
|
||||
ij_php_group_use_wrap = on_every_item
|
||||
ij_php_if_brace_force = always
|
||||
ij_php_if_lparen_on_next_line = false
|
||||
ij_php_if_rparen_on_next_line = false
|
||||
ij_php_ignore_weight = 28
|
||||
ij_php_import_sorting = alphabetic
|
||||
ij_php_indent_break_from_case = true
|
||||
ij_php_indent_case_from_switch = true
|
||||
ij_php_indent_code_in_php_tags = false
|
||||
ij_php_internal_weight = 0
|
||||
ij_php_keep_blank_lines_after_lbrace = 2
|
||||
ij_php_keep_blank_lines_before_right_brace = 2
|
||||
ij_php_keep_blank_lines_in_code = 2
|
||||
ij_php_keep_blank_lines_in_declarations = 2
|
||||
ij_php_keep_control_statement_in_one_line = true
|
||||
ij_php_keep_first_column_comment = true
|
||||
ij_php_keep_indents_on_empty_lines = false
|
||||
ij_php_keep_line_breaks = true
|
||||
ij_php_keep_rparen_and_lbrace_on_one_line = true
|
||||
ij_php_keep_simple_methods_in_one_line = false
|
||||
ij_php_lambda_brace_style = end_of_line
|
||||
ij_php_license_weight = 28
|
||||
ij_php_line_comment_add_space = false
|
||||
ij_php_line_comment_at_first_column = true
|
||||
ij_php_link_weight = 28
|
||||
ij_php_lower_case_boolean_const = true
|
||||
ij_php_lower_case_null_const = true
|
||||
ij_php_method_brace_style = end_of_line
|
||||
ij_php_method_call_chain_wrap = off
|
||||
ij_php_method_parameters_new_line_after_left_paren = true
|
||||
ij_php_method_parameters_right_paren_on_new_line = true
|
||||
ij_php_method_parameters_wrap = normal
|
||||
ij_php_method_weight = 28
|
||||
ij_php_modifier_list_wrap = false
|
||||
ij_php_multiline_chained_calls_semicolon_on_new_line = false
|
||||
ij_php_namespace_brace_style = 1
|
||||
ij_php_null_type_position = in_the_end
|
||||
ij_php_package_weight = 28
|
||||
ij_php_param_weight = 4
|
||||
ij_php_parentheses_expression_new_line_after_left_paren = false
|
||||
ij_php_parentheses_expression_right_paren_on_new_line = false
|
||||
ij_php_phpdoc_blank_line_before_tags = true
|
||||
ij_php_phpdoc_blank_lines_around_parameters = true
|
||||
ij_php_phpdoc_keep_blank_lines = true
|
||||
ij_php_phpdoc_param_spaces_between_name_and_description = 1
|
||||
ij_php_phpdoc_param_spaces_between_tag_and_type = 1
|
||||
ij_php_phpdoc_param_spaces_between_type_and_name = 1
|
||||
ij_php_phpdoc_use_fqcn = true
|
||||
ij_php_phpdoc_wrap_long_lines = true
|
||||
ij_php_place_assignment_sign_on_next_line = false
|
||||
ij_php_place_parens_for_constructor = 0
|
||||
ij_php_property_read_weight = 28
|
||||
ij_php_property_weight = 28
|
||||
ij_php_property_write_weight = 28
|
||||
ij_php_return_type_on_new_line = false
|
||||
ij_php_return_weight = 5
|
||||
ij_php_see_weight = 2
|
||||
ij_php_since_weight = 28
|
||||
ij_php_sort_phpdoc_elements = true
|
||||
ij_php_space_after_colon = true
|
||||
ij_php_space_after_colon_in_return_type = true
|
||||
ij_php_space_after_comma = true
|
||||
ij_php_space_after_for_semicolon = true
|
||||
ij_php_space_after_quest = true
|
||||
ij_php_space_after_type_cast = false
|
||||
ij_php_space_after_unary_not = false
|
||||
ij_php_space_before_array_initializer_left_brace = false
|
||||
ij_php_space_before_catch_keyword = true
|
||||
ij_php_space_before_catch_left_brace = true
|
||||
ij_php_space_before_catch_parentheses = true
|
||||
ij_php_space_before_class_left_brace = true
|
||||
ij_php_space_before_closure_left_parenthesis = true
|
||||
ij_php_space_before_colon = true
|
||||
ij_php_space_before_colon_in_return_type = false
|
||||
ij_php_space_before_comma = false
|
||||
ij_php_space_before_do_left_brace = true
|
||||
ij_php_space_before_else_keyword = true
|
||||
ij_php_space_before_else_left_brace = true
|
||||
ij_php_space_before_finally_keyword = true
|
||||
ij_php_space_before_finally_left_brace = true
|
||||
ij_php_space_before_for_left_brace = true
|
||||
ij_php_space_before_for_parentheses = true
|
||||
ij_php_space_before_for_semicolon = false
|
||||
ij_php_space_before_if_left_brace = true
|
||||
ij_php_space_before_if_parentheses = true
|
||||
ij_php_space_before_method_call_parentheses = false
|
||||
ij_php_space_before_method_left_brace = true
|
||||
ij_php_space_before_method_parentheses = false
|
||||
ij_php_space_before_quest = true
|
||||
ij_php_space_before_switch_left_brace = true
|
||||
ij_php_space_before_switch_parentheses = true
|
||||
ij_php_space_before_try_left_brace = true
|
||||
ij_php_space_before_unary_not = false
|
||||
ij_php_space_before_while_keyword = true
|
||||
ij_php_space_before_while_left_brace = true
|
||||
ij_php_space_before_while_parentheses = true
|
||||
ij_php_space_between_ternary_quest_and_colon = false
|
||||
ij_php_spaces_around_additive_operators = true
|
||||
ij_php_spaces_around_arrow = false
|
||||
ij_php_spaces_around_assignment_in_declare = false
|
||||
ij_php_spaces_around_assignment_operators = true
|
||||
ij_php_spaces_around_bitwise_operators = true
|
||||
ij_php_spaces_around_equality_operators = true
|
||||
ij_php_spaces_around_logical_operators = true
|
||||
ij_php_spaces_around_multiplicative_operators = true
|
||||
ij_php_spaces_around_null_coalesce_operator = true
|
||||
ij_php_spaces_around_relational_operators = true
|
||||
ij_php_spaces_around_shift_operators = true
|
||||
ij_php_spaces_around_unary_operator = false
|
||||
ij_php_spaces_around_var_within_brackets = false
|
||||
ij_php_spaces_within_array_initializer_braces = false
|
||||
ij_php_spaces_within_brackets = false
|
||||
ij_php_spaces_within_catch_parentheses = false
|
||||
ij_php_spaces_within_for_parentheses = false
|
||||
ij_php_spaces_within_if_parentheses = false
|
||||
ij_php_spaces_within_method_call_parentheses = false
|
||||
ij_php_spaces_within_method_parentheses = false
|
||||
ij_php_spaces_within_parentheses = false
|
||||
ij_php_spaces_within_short_echo_tags = true
|
||||
ij_php_spaces_within_switch_parentheses = false
|
||||
ij_php_spaces_within_while_parentheses = false
|
||||
ij_php_special_else_if_treatment = false
|
||||
ij_php_subpackage_weight = 28
|
||||
ij_php_ternary_operation_signs_on_next_line = false
|
||||
ij_php_ternary_operation_wrap = off
|
||||
ij_php_throws_weight = 6
|
||||
ij_php_todo_weight = 28
|
||||
ij_php_unknown_tag_weight = 28
|
||||
ij_php_upper_case_boolean_const = false
|
||||
ij_php_upper_case_null_const = false
|
||||
ij_php_uses_weight = 28
|
||||
ij_php_var_weight = 28
|
||||
ij_php_variable_naming_style = mixed
|
||||
ij_php_version_weight = 28
|
||||
ij_php_while_brace_force = always
|
||||
ij_php_while_on_new_line = false
|
||||
ij_xml_align_attributes = true
|
||||
ij_xml_align_text = false
|
||||
ij_xml_attribute_wrap = normal
|
||||
ij_xml_block_comment_at_first_column = true
|
||||
ij_xml_keep_blank_lines = 2
|
||||
ij_xml_keep_indents_on_empty_lines = false
|
||||
ij_xml_keep_line_breaks = false
|
||||
ij_xml_keep_line_breaks_in_text = true
|
||||
ij_xml_keep_whitespaces = false
|
||||
ij_xml_keep_whitespaces_around_cdata = preserve
|
||||
ij_xml_keep_whitespaces_inside_cdata = true
|
||||
ij_xml_line_comment_at_first_column = true
|
||||
ij_xml_space_after_tag_name = false
|
||||
ij_xml_space_around_equals_in_attribute = false
|
||||
ij_xml_space_inside_empty_tag = false
|
||||
ij_xml_text_wrap = normal
|
||||
|
||||
[{*.js,*.cjs}]
|
||||
[{*.bash,*.sh,*.zsh}]
|
||||
indent_size = 2
|
||||
tab_width = 2
|
||||
ij_shell_binary_ops_start_line = false
|
||||
ij_shell_keep_column_alignment_padding = false
|
||||
ij_shell_minify_program = false
|
||||
ij_shell_redirect_followed_by_space = false
|
||||
ij_shell_switch_cases_indented = false
|
||||
|
||||
[{*.cjs,*.js}]
|
||||
indent_style = tab
|
||||
ij_continuation_indent_size = 4
|
||||
ij_smart_tabs = true
|
||||
@@ -296,13 +126,13 @@ ij_javascript_array_initializer_wrap = off
|
||||
ij_javascript_assignment_wrap = off
|
||||
ij_javascript_binary_operation_sign_on_next_line = false
|
||||
ij_javascript_binary_operation_wrap = off
|
||||
ij_javascript_blacklist_imports = rxjs/Rx,node_modules/**/*,@angular/material,@angular/material/typings/**
|
||||
ij_javascript_blacklist_imports = rxjs/Rx,node_modules/**,**/node_modules/**,@angular/material,@angular/material/typings/**
|
||||
ij_javascript_blank_lines_after_imports = 1
|
||||
ij_javascript_blank_lines_around_class = 1
|
||||
ij_javascript_blank_lines_around_field = 0
|
||||
ij_javascript_blank_lines_around_function = 1
|
||||
ij_javascript_blank_lines_around_method = 1
|
||||
ij_javascript_block_brace_style = end_of_line
|
||||
ij_javascript_block_brace_style = next_line
|
||||
ij_javascript_call_parameters_new_line_after_left_paren = false
|
||||
ij_javascript_call_parameters_right_paren_on_new_line = false
|
||||
ij_javascript_call_parameters_wrap = off
|
||||
@@ -310,7 +140,7 @@ ij_javascript_catch_on_new_line = false
|
||||
ij_javascript_chained_call_dot_on_new_line = true
|
||||
ij_javascript_class_brace_style = end_of_line
|
||||
ij_javascript_comma_on_new_line = false
|
||||
ij_javascript_do_while_brace_force = always
|
||||
ij_javascript_do_while_brace_force = never
|
||||
ij_javascript_else_on_new_line = true
|
||||
ij_javascript_enforce_trailing_comma = keep
|
||||
ij_javascript_extends_keyword_wrap = off
|
||||
@@ -318,7 +148,7 @@ ij_javascript_extends_list_wrap = off
|
||||
ij_javascript_field_prefix = _
|
||||
ij_javascript_file_name_style = relaxed
|
||||
ij_javascript_finally_on_new_line = false
|
||||
ij_javascript_for_brace_force = always
|
||||
ij_javascript_for_brace_force = never
|
||||
ij_javascript_for_statement_new_line_after_left_paren = false
|
||||
ij_javascript_for_statement_right_paren_on_new_line = false
|
||||
ij_javascript_for_statement_wrap = off
|
||||
@@ -354,6 +184,9 @@ ij_javascript_parentheses_expression_new_line_after_left_paren = false
|
||||
ij_javascript_parentheses_expression_right_paren_on_new_line = false
|
||||
ij_javascript_place_assignment_sign_on_next_line = false
|
||||
ij_javascript_prefer_as_type_cast = false
|
||||
ij_javascript_prefer_explicit_types_function_expression_returns = false
|
||||
ij_javascript_prefer_explicit_types_function_returns = false
|
||||
ij_javascript_prefer_explicit_types_vars_fields = false
|
||||
ij_javascript_prefer_parameters_wrap = false
|
||||
ij_javascript_reformat_c_style_comments = false
|
||||
ij_javascript_space_after_colon = true
|
||||
@@ -434,11 +267,237 @@ ij_javascript_use_path_mapping = always
|
||||
ij_javascript_use_public_modifier = false
|
||||
ij_javascript_use_semicolon_after_statement = true
|
||||
ij_javascript_var_declaration_wrap = normal
|
||||
ij_javascript_while_brace_force = always
|
||||
ij_javascript_while_brace_force = never
|
||||
ij_javascript_while_on_new_line = false
|
||||
ij_javascript_wrap_comments = false
|
||||
|
||||
[{*.sht,*.html,*.shtm,*.shtml,*.htm,*.ng}]
|
||||
[{*.ctp,*.hphp,*.inc,*.module,*.php,*.php4,*.php5,*.phtml}]
|
||||
indent_style = tab
|
||||
ij_continuation_indent_size = 4
|
||||
ij_smart_tabs = true
|
||||
ij_wrap_on_typing = false
|
||||
ij_php_align_assignments = false
|
||||
ij_php_align_class_constants = false
|
||||
ij_php_align_group_field_declarations = false
|
||||
ij_php_align_inline_comments = false
|
||||
ij_php_align_key_value_pairs = false
|
||||
ij_php_align_multiline_array_initializer_expression = false
|
||||
ij_php_align_multiline_binary_operation = false
|
||||
ij_php_align_multiline_chained_methods = false
|
||||
ij_php_align_multiline_extends_list = false
|
||||
ij_php_align_multiline_for = true
|
||||
ij_php_align_multiline_parameters = false
|
||||
ij_php_align_multiline_parameters_in_calls = false
|
||||
ij_php_align_multiline_ternary_operation = false
|
||||
ij_php_align_phpdoc_comments = false
|
||||
ij_php_align_phpdoc_param_names = false
|
||||
ij_php_anonymous_brace_style = end_of_line
|
||||
ij_php_api_weight = 1
|
||||
ij_php_array_initializer_new_line_after_left_brace = true
|
||||
ij_php_array_initializer_right_brace_on_new_line = true
|
||||
ij_php_array_initializer_wrap = on_every_item
|
||||
ij_php_assignment_wrap = off
|
||||
ij_php_author_weight = 8
|
||||
ij_php_binary_operation_sign_on_next_line = false
|
||||
ij_php_binary_operation_wrap = off
|
||||
ij_php_blank_lines_after_class_header = 0
|
||||
ij_php_blank_lines_after_function = 1
|
||||
ij_php_blank_lines_after_imports = 1
|
||||
ij_php_blank_lines_after_opening_tag = 0
|
||||
ij_php_blank_lines_after_package = 1
|
||||
ij_php_blank_lines_around_class = 1
|
||||
ij_php_blank_lines_around_constants = 0
|
||||
ij_php_blank_lines_around_field = 0
|
||||
ij_php_blank_lines_around_method = 1
|
||||
ij_php_blank_lines_before_class_end = 0
|
||||
ij_php_blank_lines_before_imports = 1
|
||||
ij_php_blank_lines_before_method_body = 0
|
||||
ij_php_blank_lines_before_package = 1
|
||||
ij_php_blank_lines_before_return_statement = 1
|
||||
ij_php_blank_lines_between_imports = 0
|
||||
ij_php_block_brace_style = end_of_line
|
||||
ij_php_call_parameters_new_line_after_left_paren = false
|
||||
ij_php_call_parameters_right_paren_on_new_line = false
|
||||
ij_php_call_parameters_wrap = normal
|
||||
ij_php_catch_on_new_line = true
|
||||
ij_php_category_weight = 28
|
||||
ij_php_class_brace_style = next_line
|
||||
ij_php_comma_after_last_array_element = true
|
||||
ij_php_concat_spaces = false
|
||||
ij_php_copyright_weight = 28
|
||||
ij_php_deprecated_weight = 2
|
||||
ij_php_do_while_brace_force = always
|
||||
ij_php_else_if_style = as_is
|
||||
ij_php_else_on_new_line = false
|
||||
ij_php_example_weight = 4
|
||||
ij_php_extends_keyword_wrap = off
|
||||
ij_php_extends_list_wrap = off
|
||||
ij_php_fields_default_visibility = private
|
||||
ij_php_filesource_weight = 28
|
||||
ij_php_finally_on_new_line = true
|
||||
ij_php_for_brace_force = always
|
||||
ij_php_for_statement_new_line_after_left_paren = false
|
||||
ij_php_for_statement_right_paren_on_new_line = false
|
||||
ij_php_for_statement_wrap = off
|
||||
ij_php_force_short_declaration_array_style = false
|
||||
ij_php_getters_setters_naming_style = camel_case
|
||||
ij_php_getters_setters_order_style = getters_first
|
||||
ij_php_global_weight = 28
|
||||
ij_php_group_use_wrap = on_every_item
|
||||
ij_php_if_brace_force = always
|
||||
ij_php_if_lparen_on_next_line = false
|
||||
ij_php_if_rparen_on_next_line = false
|
||||
ij_php_ignore_weight = 28
|
||||
ij_php_import_sorting = alphabetic
|
||||
ij_php_indent_break_from_case = true
|
||||
ij_php_indent_case_from_switch = true
|
||||
ij_php_indent_code_in_php_tags = false
|
||||
ij_php_internal_weight = 0
|
||||
ij_php_keep_blank_lines_after_lbrace = 2
|
||||
ij_php_keep_blank_lines_before_right_brace = 2
|
||||
ij_php_keep_blank_lines_in_code = 2
|
||||
ij_php_keep_blank_lines_in_declarations = 2
|
||||
ij_php_keep_control_statement_in_one_line = true
|
||||
ij_php_keep_first_column_comment = true
|
||||
ij_php_keep_indents_on_empty_lines = false
|
||||
ij_php_keep_line_breaks = true
|
||||
ij_php_keep_rparen_and_lbrace_on_one_line = true
|
||||
ij_php_keep_simple_classes_in_one_line = false
|
||||
ij_php_keep_simple_methods_in_one_line = false
|
||||
ij_php_lambda_brace_style = end_of_line
|
||||
ij_php_license_weight = 28
|
||||
ij_php_line_comment_add_space = false
|
||||
ij_php_line_comment_at_first_column = true
|
||||
ij_php_link_weight = 28
|
||||
ij_php_lower_case_boolean_const = true
|
||||
ij_php_lower_case_keywords = true
|
||||
ij_php_lower_case_null_const = true
|
||||
ij_php_method_brace_style = next_line
|
||||
ij_php_method_call_chain_wrap = off
|
||||
ij_php_method_parameters_new_line_after_left_paren = true
|
||||
ij_php_method_parameters_right_paren_on_new_line = true
|
||||
ij_php_method_parameters_wrap = normal
|
||||
ij_php_method_weight = 28
|
||||
ij_php_modifier_list_wrap = false
|
||||
ij_php_multiline_chained_calls_semicolon_on_new_line = false
|
||||
ij_php_namespace_brace_style = 1
|
||||
ij_php_new_line_after_php_opening_tag = false
|
||||
ij_php_null_type_position = in_the_end
|
||||
ij_php_package_weight = 28
|
||||
ij_php_param_weight = 5
|
||||
ij_php_parentheses_expression_new_line_after_left_paren = false
|
||||
ij_php_parentheses_expression_right_paren_on_new_line = false
|
||||
ij_php_phpdoc_blank_line_before_tags = true
|
||||
ij_php_phpdoc_blank_lines_around_parameters = true
|
||||
ij_php_phpdoc_keep_blank_lines = true
|
||||
ij_php_phpdoc_param_spaces_between_name_and_description = 1
|
||||
ij_php_phpdoc_param_spaces_between_tag_and_type = 1
|
||||
ij_php_phpdoc_param_spaces_between_type_and_name = 1
|
||||
ij_php_phpdoc_use_fqcn = true
|
||||
ij_php_phpdoc_wrap_long_lines = true
|
||||
ij_php_place_assignment_sign_on_next_line = false
|
||||
ij_php_place_parens_for_constructor = 0
|
||||
ij_php_property_read_weight = 28
|
||||
ij_php_property_weight = 28
|
||||
ij_php_property_write_weight = 28
|
||||
ij_php_return_type_on_new_line = false
|
||||
ij_php_return_weight = 6
|
||||
ij_php_see_weight = 3
|
||||
ij_php_since_weight = 28
|
||||
ij_php_sort_phpdoc_elements = true
|
||||
ij_php_space_after_colon = true
|
||||
ij_php_space_after_colon_in_return_type = true
|
||||
ij_php_space_after_comma = true
|
||||
ij_php_space_after_for_semicolon = true
|
||||
ij_php_space_after_quest = true
|
||||
ij_php_space_after_type_cast = false
|
||||
ij_php_space_after_unary_not = false
|
||||
ij_php_space_before_array_initializer_left_brace = false
|
||||
ij_php_space_before_catch_keyword = true
|
||||
ij_php_space_before_catch_left_brace = true
|
||||
ij_php_space_before_catch_parentheses = true
|
||||
ij_php_space_before_class_left_brace = true
|
||||
ij_php_space_before_closure_left_parenthesis = true
|
||||
ij_php_space_before_colon = true
|
||||
ij_php_space_before_colon_in_return_type = false
|
||||
ij_php_space_before_comma = false
|
||||
ij_php_space_before_do_left_brace = true
|
||||
ij_php_space_before_else_keyword = true
|
||||
ij_php_space_before_else_left_brace = true
|
||||
ij_php_space_before_finally_keyword = true
|
||||
ij_php_space_before_finally_left_brace = true
|
||||
ij_php_space_before_for_left_brace = true
|
||||
ij_php_space_before_for_parentheses = true
|
||||
ij_php_space_before_for_semicolon = false
|
||||
ij_php_space_before_if_left_brace = true
|
||||
ij_php_space_before_if_parentheses = true
|
||||
ij_php_space_before_method_call_parentheses = false
|
||||
ij_php_space_before_method_left_brace = true
|
||||
ij_php_space_before_method_parentheses = false
|
||||
ij_php_space_before_quest = true
|
||||
ij_php_space_before_short_closure_left_parenthesis = false
|
||||
ij_php_space_before_switch_left_brace = true
|
||||
ij_php_space_before_switch_parentheses = true
|
||||
ij_php_space_before_try_left_brace = true
|
||||
ij_php_space_before_unary_not = false
|
||||
ij_php_space_before_while_keyword = true
|
||||
ij_php_space_before_while_left_brace = true
|
||||
ij_php_space_before_while_parentheses = true
|
||||
ij_php_space_between_ternary_quest_and_colon = false
|
||||
ij_php_spaces_around_additive_operators = true
|
||||
ij_php_spaces_around_arrow = false
|
||||
ij_php_spaces_around_assignment_in_declare = false
|
||||
ij_php_spaces_around_assignment_operators = true
|
||||
ij_php_spaces_around_bitwise_operators = true
|
||||
ij_php_spaces_around_equality_operators = true
|
||||
ij_php_spaces_around_logical_operators = true
|
||||
ij_php_spaces_around_multiplicative_operators = true
|
||||
ij_php_spaces_around_null_coalesce_operator = true
|
||||
ij_php_spaces_around_relational_operators = true
|
||||
ij_php_spaces_around_shift_operators = true
|
||||
ij_php_spaces_around_unary_operator = false
|
||||
ij_php_spaces_around_var_within_brackets = false
|
||||
ij_php_spaces_within_array_initializer_braces = false
|
||||
ij_php_spaces_within_brackets = false
|
||||
ij_php_spaces_within_catch_parentheses = false
|
||||
ij_php_spaces_within_for_parentheses = false
|
||||
ij_php_spaces_within_if_parentheses = false
|
||||
ij_php_spaces_within_method_call_parentheses = false
|
||||
ij_php_spaces_within_method_parentheses = false
|
||||
ij_php_spaces_within_parentheses = false
|
||||
ij_php_spaces_within_short_echo_tags = true
|
||||
ij_php_spaces_within_switch_parentheses = false
|
||||
ij_php_spaces_within_while_parentheses = false
|
||||
ij_php_special_else_if_treatment = true
|
||||
ij_php_subpackage_weight = 28
|
||||
ij_php_ternary_operation_signs_on_next_line = false
|
||||
ij_php_ternary_operation_wrap = off
|
||||
ij_php_throws_weight = 7
|
||||
ij_php_todo_weight = 28
|
||||
ij_php_unknown_tag_weight = 28
|
||||
ij_php_upper_case_boolean_const = false
|
||||
ij_php_upper_case_null_const = false
|
||||
ij_php_uses_weight = 28
|
||||
ij_php_var_weight = 28
|
||||
ij_php_variable_naming_style = mixed
|
||||
ij_php_version_weight = 28
|
||||
ij_php_while_brace_force = always
|
||||
ij_php_while_on_new_line = false
|
||||
|
||||
[{*.har,*.jsb2,*.jsb3,*.json,.babelrc,.eslintrc,.stylelintrc,bowerrc,composer.lock,jest.config}]
|
||||
indent_size = 2
|
||||
ij_json_keep_blank_lines_in_code = 0
|
||||
ij_json_keep_indents_on_empty_lines = false
|
||||
ij_json_keep_line_breaks = true
|
||||
ij_json_space_after_colon = true
|
||||
ij_json_space_after_comma = true
|
||||
ij_json_space_before_colon = true
|
||||
ij_json_space_before_comma = false
|
||||
ij_json_spaces_within_braces = false
|
||||
ij_json_spaces_within_brackets = false
|
||||
ij_json_wrap_long_lines = false
|
||||
|
||||
[{*.htm,*.html,*.sht,*.shtm,*.shtml}]
|
||||
indent_style = tab
|
||||
ij_smart_tabs = true
|
||||
ij_html_add_new_line_before_tags = body,div,p,form,h1,h2,h3
|
||||
@@ -460,44 +519,18 @@ ij_html_keep_whitespaces_inside = span,pre,textarea
|
||||
ij_html_line_comment_at_first_column = true
|
||||
ij_html_new_line_after_last_attribute = never
|
||||
ij_html_new_line_before_first_attribute = never
|
||||
ij_html_quote_style = double
|
||||
ij_html_quote_style = none
|
||||
ij_html_remove_new_line_before_tags = br
|
||||
ij_html_space_after_tag_name = false
|
||||
ij_html_space_around_equality_in_attribute = false
|
||||
ij_html_space_inside_empty_tag = false
|
||||
ij_html_text_wrap = normal
|
||||
ij_html_uniform_ident = false
|
||||
|
||||
[{*.yml,*.yaml}]
|
||||
[{*.yaml,*.yml}]
|
||||
indent_size = 2
|
||||
ij_continuation_indent_size = 2
|
||||
ij_yaml_keep_indents_on_empty_lines = false
|
||||
ij_yaml_keep_line_breaks = true
|
||||
|
||||
[{*.zsh,*.sh,*.bash}]
|
||||
ij_shell_binary_ops_start_line = false
|
||||
ij_shell_keep_column_alignment_padding = false
|
||||
ij_shell_minify_program = false
|
||||
ij_shell_redirect_followed_by_space = false
|
||||
ij_shell_switch_cases_indented = false
|
||||
|
||||
[{.babelrc,.stylelintrc,.eslintrc,jest.config,*.json,*.jsb3,*.jsb2,*.bowerrc}]
|
||||
indent_size = 2
|
||||
ij_json_keep_blank_lines_in_code = 0
|
||||
ij_json_keep_indents_on_empty_lines = false
|
||||
ij_json_keep_line_breaks = true
|
||||
ij_json_space_after_colon = true
|
||||
ij_json_space_after_comma = true
|
||||
ij_json_space_before_colon = true
|
||||
ij_json_space_before_comma = false
|
||||
ij_json_spaces_within_braces = false
|
||||
ij_json_spaces_within_brackets = false
|
||||
ij_json_wrap_long_lines = false
|
||||
|
||||
[{phpunit.xml.dist,*.xslt,*.xul,*.rng,*.xsl,*.xsd,*.ant,*.jhm,*.tld,*.fxml,*.wsdl,*.jrxml,*.xml,*.jnlp}]
|
||||
indent_size = 2
|
||||
indent_style = tab
|
||||
tab_width = 2
|
||||
ij_smart_tabs = true
|
||||
ij_xml_block_comment_at_first_column = true
|
||||
ij_xml_keep_indents_on_empty_lines = false
|
||||
ij_xml_line_comment_at_first_column = true
|
||||
ij_yaml_space_before_colon = true
|
||||
ij_yaml_spaces_within_braces = true
|
||||
ij_yaml_spaces_within_brackets = true
|
||||
|
||||
@@ -1020,19 +1020,19 @@ class utils
|
||||
throw new Exception("The path to php must not be empty. Please set a value for 'php_path' in your configuration file.");
|
||||
}
|
||||
|
||||
$sAuthUser = self::ReadParam('auth_user', '', 'raw_data');
|
||||
$sAuthPwd = self::ReadParam('auth_pwd', '', 'raw_data');
|
||||
$sParamFile = self::GetParamSourceFile('auth_user');
|
||||
if (is_null($sParamFile))
|
||||
{
|
||||
if (!isset($aArguments['auth_user'])) {
|
||||
$sAuthUser = self::ReadParam('auth_user', '', 'raw_data');
|
||||
$aArguments['auth_user'] = $sAuthUser;
|
||||
}
|
||||
if (!isset($aArguments['auth_pwd'])) {
|
||||
$sAuthPwd = self::ReadParam('auth_pwd', '', 'raw_data');
|
||||
$aArguments['auth_pwd'] = $sAuthPwd;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!isset($aArguments['param_file'])) {
|
||||
$sParamFile = self::ReadParam('param_file', '', 'raw_data');
|
||||
$aArguments['param_file'] = $sParamFile;
|
||||
}
|
||||
|
||||
|
||||
$aArgs = array();
|
||||
foreach($aArguments as $sName => $value)
|
||||
{
|
||||
|
||||
@@ -188,7 +188,9 @@ class ActionEmail extends ActionNotification
|
||||
MetaModel::Init_AddAttribute(new AttributeEmailAddress("test_recipient", array("allowed_values"=>null, "sql"=>"test_recipient", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
|
||||
|
||||
MetaModel::Init_AddAttribute(new AttributeString("from", array("allowed_values"=>null, "sql"=>"from", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeString("from_label", array("allowed_values"=>null, "sql"=>"from_label", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeString("reply_to", array("allowed_values"=>null, "sql"=>"reply_to", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeString("reply_to_label", array("allowed_values"=>null, "sql"=>"reply_to_label", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeOQL("to", array("allowed_values"=>null, "sql"=>"to", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeOQL("cc", array("allowed_values"=>null, "sql"=>"cc", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeOQL("bcc", array("allowed_values"=>null, "sql"=>"bcc", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
|
||||
@@ -198,7 +200,7 @@ class ActionEmail extends ActionNotification
|
||||
|
||||
// Display lists
|
||||
// - Attributes to be displayed for the complete details
|
||||
MetaModel::Init_SetZListItems('details', array('name', 'description', 'status', 'test_recipient', 'from', 'reply_to', 'to', 'cc', 'bcc', 'subject', 'body', 'importance', 'trigger_list'));
|
||||
MetaModel::Init_SetZListItems('details', array('name', 'description', 'status', 'test_recipient', 'from', 'from_label', 'reply_to', 'reply_to_label', 'to', 'cc', 'bcc', 'subject', 'body', 'importance', 'trigger_list'));
|
||||
// - Attributes to be displayed for a list
|
||||
MetaModel::Init_SetZListItems('list', array('name', 'status', 'to', 'subject'));
|
||||
// Search criteria
|
||||
@@ -371,10 +373,12 @@ class ActionEmail extends ActionNotification
|
||||
$sTo = $this->FindRecipients('to', $aContextArgs);
|
||||
$sCC = $this->FindRecipients('cc', $aContextArgs);
|
||||
$sBCC = $this->FindRecipients('bcc', $aContextArgs);
|
||||
|
||||
|
||||
$sFrom = MetaModel::ApplyParams($this->Get('from'), $aContextArgs);
|
||||
$sFromLabel = MetaModel::ApplyParams($this->Get('from_label'), $aContextArgs);
|
||||
$sReplyTo = MetaModel::ApplyParams($this->Get('reply_to'), $aContextArgs);
|
||||
|
||||
$sReplyToLabel = MetaModel::ApplyParams($this->Get('reply_to_label'), $aContextArgs);
|
||||
|
||||
$sSubject = MetaModel::ApplyParams($this->Get('subject'), $aContextArgs);
|
||||
$sBody = MetaModel::ApplyParams($this->Get('body'), $aContextArgs);
|
||||
|
||||
@@ -397,7 +401,7 @@ class ActionEmail extends ActionNotification
|
||||
if (isset($sTo)) $oLog->Set('to', $sTo);
|
||||
if (isset($sCC)) $oLog->Set('cc', $sCC);
|
||||
if (isset($sBCC)) $oLog->Set('bcc', $sBCC);
|
||||
if (isset($sFrom)) $oLog->Set('from', $sFrom);
|
||||
if (isset($sFrom)) $oLog->Set('from', empty($sFromLabel) ? $sFrom : "$sFromLabel <$sFrom>");
|
||||
if (isset($sSubject)) $oLog->Set('subject', $sSubject);
|
||||
if (isset($sBody)) $oLog->Set('body', $sBody);
|
||||
}
|
||||
@@ -417,15 +421,15 @@ class ActionEmail extends ActionNotification
|
||||
$sTestBody .= "<li>TO: $sTo</li>\n";
|
||||
$sTestBody .= "<li>CC: $sCC</li>\n";
|
||||
$sTestBody .= "<li>BCC: $sBCC</li>\n";
|
||||
$sTestBody .= "<li>From: $sFrom</li>\n";
|
||||
$sTestBody .= "<li>Reply-To: $sReplyTo</li>\n";
|
||||
$sTestBody .= empty($sFromLabel) ? "<li>From: $sFrom</li>\n": "<li>From: $sFromLabel <$sFrom></li>\n";
|
||||
$sTestBody .= empty($sReplyToLabel) ? "<li>Reply-To: $sReplyTo</li>\n": "<li>Reply-To: $sReplyToLabel <$sReplyTo></li>\n";
|
||||
$sTestBody .= "<li>References: $sReference</li>\n";
|
||||
$sTestBody .= "</ul>\n";
|
||||
$sTestBody .= "</p>\n";
|
||||
$sTestBody .= "</div>\n";
|
||||
$oEmail->SetBody($sTestBody, 'text/html', $sStyles);
|
||||
$oEmail->SetRecipientTO($this->Get('test_recipient'));
|
||||
$oEmail->SetRecipientFrom($sFrom);
|
||||
$oEmail->SetRecipientFrom($sFrom, $sFromLabel);
|
||||
$oEmail->SetReferences($sReference);
|
||||
$oEmail->SetMessageId($sMessageId);
|
||||
}
|
||||
@@ -436,8 +440,8 @@ class ActionEmail extends ActionNotification
|
||||
$oEmail->SetRecipientTO($sTo);
|
||||
$oEmail->SetRecipientCC($sCC);
|
||||
$oEmail->SetRecipientBCC($sBCC);
|
||||
$oEmail->SetRecipientFrom($sFrom);
|
||||
$oEmail->SetRecipientReplyTo($sReplyTo);
|
||||
$oEmail->SetRecipientFrom($sFrom, $sFromLabel);
|
||||
$oEmail->SetRecipientReplyTo($sReplyTo, $sReplyToLabel);
|
||||
$oEmail->SetReferences($sReference);
|
||||
$oEmail->SetMessageId($sMessageId);
|
||||
}
|
||||
|
||||
@@ -846,13 +846,17 @@ abstract class DBObject implements iDisplay
|
||||
}
|
||||
|
||||
/**
|
||||
* @see \DBObject::ListPreviousValuesForUpdatedAttributes() to get previous values anywhere in the CRUD stack
|
||||
* @see https://www.itophub.io/wiki/page?id=latest%3Acustomization%3Asequence_crud iTop CRUD stack documentation
|
||||
*
|
||||
* @param string $sAttCode
|
||||
*
|
||||
* @return mixed|null the value as it was before changed with {@see DBObject::Set()}.
|
||||
* Returns null if the attribute wasn't changed.
|
||||
* Values are reset during {@see DBObject::DBUpdate()}
|
||||
*
|
||||
* @see DBObject::$m_aOrigValues
|
||||
* @throws CoreException if the attribute is unknown for the current object
|
||||
* @uses DBObject::$m_aOrigValues
|
||||
*/
|
||||
public function GetOriginal($sAttCode)
|
||||
{
|
||||
@@ -2365,14 +2369,16 @@ abstract class DBObject implements iDisplay
|
||||
return $aDelta;
|
||||
}
|
||||
|
||||
/**
|
||||
* @api
|
||||
* @api-advanced
|
||||
*
|
||||
* @return array attname => currentvalue List the attributes that have been changed using {@see DBObject::Set()}. Reset during {@see DBObject::DBUpdate()}
|
||||
* @uses m_aCurrValues
|
||||
* @see \DBObject::ListPreviousValuesForUpdatedAttributes()
|
||||
* @throws Exception
|
||||
/**
|
||||
* @api
|
||||
* @api-advanced
|
||||
*
|
||||
* @see \DBObject::ListPreviousValuesForUpdatedAttributes() to get previous values anywhere in the CRUD stack
|
||||
* @see https://www.itophub.io/wiki/page?id=latest%3Acustomization%3Asequence_crud iTop CRUD stack documentation
|
||||
* @return array attname => currentvalue List the attributes that have been changed using {@see DBObject::Set()}.
|
||||
* Reset during {@see DBObject::DBUpdate()}
|
||||
* @throws Exception
|
||||
* @uses m_aCurrValues
|
||||
*/
|
||||
public function ListChanges()
|
||||
{
|
||||
@@ -2392,10 +2398,10 @@ abstract class DBObject implements iDisplay
|
||||
*
|
||||
* To get values that were set to the changed fields, simply use {@link \DBObject::Get()}
|
||||
*
|
||||
* @see \DBObject::ListChanges() old method, but using data that are reset during DBObject::DBUpdate
|
||||
* @return array attname => value : value that was present before the last {@see DBObject::Set()} call.
|
||||
* This array is set at the beginning of {@see DBObject::DBpdate()} using {@see DBObject::InitPreviousValuesForUpdatedAttributes()}.
|
||||
* @uses m_aPreviousValuesForUpdatedAttributes
|
||||
* @see \DBObject::ListChanges()
|
||||
* @since 2.7.0 N°2293
|
||||
*/
|
||||
public function ListPreviousValuesForUpdatedAttributes()
|
||||
|
||||
@@ -100,7 +100,7 @@ class EMail
|
||||
}
|
||||
if (array_key_exists('reply_to', $aData))
|
||||
{
|
||||
$oMessage->SetRecipientReplyTo($aData['reply_to']);
|
||||
$oMessage->SetRecipientReplyTo($aData['reply_to']['address'], $aData['reply_to']['label']);
|
||||
}
|
||||
if (array_key_exists('to', $aData))
|
||||
{
|
||||
@@ -465,10 +465,14 @@ class EMail
|
||||
}
|
||||
}
|
||||
|
||||
public function SetRecipientReplyTo($sAddress)
|
||||
public function SetRecipientReplyTo($sAddress, $sLabel = '')
|
||||
{
|
||||
$this->m_aData['reply_to'] = $sAddress;
|
||||
if (!empty($sAddress))
|
||||
$this->m_aData['reply_to'] = array('address' => $sAddress, 'label' => $sLabel);
|
||||
if ($sLabel != '')
|
||||
{
|
||||
$this->m_oMessage->setReplyTo(array($sAddress => $sLabel));
|
||||
}
|
||||
else if (!empty($sAddress))
|
||||
{
|
||||
$this->m_oMessage->setReplyTo($sAddress);
|
||||
}
|
||||
|
||||
@@ -507,10 +507,14 @@ Dict::Add('CS CZ', 'Czech', 'Čeština', array(
|
||||
'Class:ActionEmail+' => '',
|
||||
'Class:ActionEmail/Attribute:test_recipient' => 'Adresát pro test',
|
||||
'Class:ActionEmail/Attribute:test_recipient+' => 'Cílová adresa pro případ, kdy je stav nastaven na "Testování"',
|
||||
'Class:ActionEmail/Attribute:from' => 'Odesílatel',
|
||||
'Class:ActionEmail/Attribute:from+' => '',
|
||||
'Class:ActionEmail/Attribute:reply_to' => 'Odpověď na',
|
||||
'Class:ActionEmail/Attribute:reply_to+' => '',
|
||||
'Class:ActionEmail/Attribute:from' => 'Odesílatel~~',
|
||||
'Class:ActionEmail/Attribute:from+' => '~~',
|
||||
'Class:ActionEmail/Attribute:from_label' => 'From (label)~~',
|
||||
'Class:ActionEmail/Attribute:from_label+' => 'Sender display name will be sent into the email header~~',
|
||||
'Class:ActionEmail/Attribute:reply_to' => 'Odpověď na~~',
|
||||
'Class:ActionEmail/Attribute:reply_to+' => '~~',
|
||||
'Class:ActionEmail/Attribute:reply_to_label' => 'Reply to (label)~~',
|
||||
'Class:ActionEmail/Attribute:reply_to_label+' => 'Reply to display name will be sent into the email header~~',
|
||||
'Class:ActionEmail/Attribute:to' => 'To',
|
||||
'Class:ActionEmail/Attribute:to+' => 'Adresát',
|
||||
'Class:ActionEmail/Attribute:cc' => 'Cc',
|
||||
|
||||
@@ -505,10 +505,14 @@ Dict::Add('DA DA', 'Danish', 'Dansk', array(
|
||||
'Class:ActionEmail+' => '',
|
||||
'Class:ActionEmail/Attribute:test_recipient' => 'Test modtager',
|
||||
'Class:ActionEmail/Attribute:test_recipient+' => '',
|
||||
'Class:ActionEmail/Attribute:from' => 'Fra',
|
||||
'Class:ActionEmail/Attribute:from+' => 'Afsender af emailen',
|
||||
'Class:ActionEmail/Attribute:reply_to' => 'Svar til',
|
||||
'Class:ActionEmail/Attribute:reply_to+' => 'Svar sendes til',
|
||||
'Class:ActionEmail/Attribute:from' => 'Fra~~',
|
||||
'Class:ActionEmail/Attribute:from+' => 'Afsender af emailen~~',
|
||||
'Class:ActionEmail/Attribute:from_label' => 'From (label)~~',
|
||||
'Class:ActionEmail/Attribute:from_label+' => 'Sender display name will be sent into the email header~~',
|
||||
'Class:ActionEmail/Attribute:reply_to' => 'Svar til~~',
|
||||
'Class:ActionEmail/Attribute:reply_to+' => 'Svar sendes til~~',
|
||||
'Class:ActionEmail/Attribute:reply_to_label' => 'Reply to (label)~~',
|
||||
'Class:ActionEmail/Attribute:reply_to_label+' => 'Reply to display name will be sent into the email header~~',
|
||||
'Class:ActionEmail/Attribute:to' => 'Til',
|
||||
'Class:ActionEmail/Attribute:to+' => 'Modtager af emailen',
|
||||
'Class:ActionEmail/Attribute:cc' => 'Cc',
|
||||
|
||||
@@ -504,10 +504,14 @@ Dict::Add('DE DE', 'German', 'Deutsch', array(
|
||||
'Class:ActionEmail+' => '',
|
||||
'Class:ActionEmail/Attribute:test_recipient' => 'Testempfänger',
|
||||
'Class:ActionEmail/Attribute:test_recipient+' => 'Empfänger im Fall eines "Test"-Status',
|
||||
'Class:ActionEmail/Attribute:from' => 'Von',
|
||||
'Class:ActionEmail/Attribute:from+' => 'Wird im Email-Header mitgesendet',
|
||||
'Class:ActionEmail/Attribute:reply_to' => 'Antworten an',
|
||||
'Class:ActionEmail/Attribute:from' => 'Von (E-Mail)',
|
||||
'Class:ActionEmail/Attribute:from+' => 'Absenderadresse wird im Email-Header mitgesendet',
|
||||
'Class:ActionEmail/Attribute:from_label' => 'Von (Label)',
|
||||
'Class:ActionEmail/Attribute:from_label+' => 'Absendername wird im Email-Header mitgesendet',
|
||||
'Class:ActionEmail/Attribute:reply_to' => 'Antworten an (E-Mail)',
|
||||
'Class:ActionEmail/Attribute:reply_to+' => 'Wird im Email-Header mitgesendet',
|
||||
'Class:ActionEmail/Attribute:reply_to_label' => 'Antworten an (Label)',
|
||||
'Class:ActionEmail/Attribute:reply_to_label+' => 'Wird im Email-Header mitgesendet',
|
||||
'Class:ActionEmail/Attribute:to' => 'An',
|
||||
'Class:ActionEmail/Attribute:to+' => 'Empfänger der Nachricht',
|
||||
'Class:ActionEmail/Attribute:cc' => 'Kopie an',
|
||||
|
||||
@@ -508,11 +508,15 @@ Dict::Add('EN US', 'English', 'English', array(
|
||||
'Class:ActionEmail' => 'Email notification',
|
||||
'Class:ActionEmail+' => '',
|
||||
'Class:ActionEmail/Attribute:test_recipient' => 'Test recipient',
|
||||
'Class:ActionEmail/Attribute:test_recipient+' => 'Detination in case status is set to "Test"',
|
||||
'Class:ActionEmail/Attribute:from' => 'From',
|
||||
'Class:ActionEmail/Attribute:from+' => 'Will be sent into the email header',
|
||||
'Class:ActionEmail/Attribute:reply_to' => 'Reply to',
|
||||
'Class:ActionEmail/Attribute:reply_to+' => 'Will be sent into the email header',
|
||||
'Class:ActionEmail/Attribute:test_recipient+' => 'Destination in case status is set to "Test"',
|
||||
'Class:ActionEmail/Attribute:from' => 'From (email)',
|
||||
'Class:ActionEmail/Attribute:from+' => 'Sender email address will be sent into the email header',
|
||||
'Class:ActionEmail/Attribute:from_label' => 'From (label)',
|
||||
'Class:ActionEmail/Attribute:from_label+' => 'Sender display name will be sent into the email header',
|
||||
'Class:ActionEmail/Attribute:reply_to' => 'Reply to (email)',
|
||||
'Class:ActionEmail/Attribute:reply_to+' => 'Reply to email address Will be sent into the email header',
|
||||
'Class:ActionEmail/Attribute:reply_to_label' => 'Reply to (label)',
|
||||
'Class:ActionEmail/Attribute:reply_to_label+' => 'Reply to display name will be sent into the email header',
|
||||
'Class:ActionEmail/Attribute:to' => 'To',
|
||||
'Class:ActionEmail/Attribute:to+' => 'Destination of the email',
|
||||
'Class:ActionEmail/Attribute:cc' => 'Cc',
|
||||
|
||||
@@ -505,10 +505,14 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellaño', array(
|
||||
'Class:ActionEmail+' => 'Notificación por Correo Electrónico',
|
||||
'Class:ActionEmail/Attribute:test_recipient' => 'Destinatario de Prueba',
|
||||
'Class:ActionEmail/Attribute:test_recipient+' => 'Destinatario en caso que el Estatus sea "En pruebas"',
|
||||
'Class:ActionEmail/Attribute:from' => 'Remitente',
|
||||
'Class:ActionEmail/Attribute:from+' => 'Será enviando en el encabezado del Correo Electrónico',
|
||||
'Class:ActionEmail/Attribute:reply_to' => 'Responder a',
|
||||
'Class:ActionEmail/Attribute:reply_to+' => 'Será enviando en el encabezado del Correo Electrónico',
|
||||
'Class:ActionEmail/Attribute:from' => 'Remitente~~',
|
||||
'Class:ActionEmail/Attribute:from+' => 'Será enviando en el encabezado del Correo Electrónico~~',
|
||||
'Class:ActionEmail/Attribute:from_label' => 'From (label)~~',
|
||||
'Class:ActionEmail/Attribute:from_label+' => 'Sender display name will be sent into the email header~~',
|
||||
'Class:ActionEmail/Attribute:reply_to' => 'Responder a~~',
|
||||
'Class:ActionEmail/Attribute:reply_to+' => 'Será enviando en el encabezado del Correo Electrónico~~',
|
||||
'Class:ActionEmail/Attribute:reply_to_label' => 'Reply to (label)~~',
|
||||
'Class:ActionEmail/Attribute:reply_to_label+' => 'Reply to display name will be sent into the email header~~',
|
||||
'Class:ActionEmail/Attribute:to' => 'Para',
|
||||
'Class:ActionEmail/Attribute:to+' => 'Destinatario del Correo Electrónico',
|
||||
'Class:ActionEmail/Attribute:cc' => 'CC',
|
||||
|
||||
@@ -503,10 +503,14 @@ Dict::Add('FR FR', 'French', 'Français', array(
|
||||
'Class:ActionEmail+' => '',
|
||||
'Class:ActionEmail/Attribute:test_recipient' => 'Destinataire de test',
|
||||
'Class:ActionEmail/Attribute:test_recipient+' => '',
|
||||
'Class:ActionEmail/Attribute:from' => 'De',
|
||||
'Class:ActionEmail/Attribute:from+' => '',
|
||||
'Class:ActionEmail/Attribute:reply_to' => 'Répondre à',
|
||||
'Class:ActionEmail/Attribute:reply_to+' => '',
|
||||
'Class:ActionEmail/Attribute:from' => 'De~~',
|
||||
'Class:ActionEmail/Attribute:from+' => '~~',
|
||||
'Class:ActionEmail/Attribute:from_label' => 'From (label)~~',
|
||||
'Class:ActionEmail/Attribute:from_label+' => 'Sender display name will be sent into the email header~~',
|
||||
'Class:ActionEmail/Attribute:reply_to' => 'Répondre à~~',
|
||||
'Class:ActionEmail/Attribute:reply_to+' => '~~',
|
||||
'Class:ActionEmail/Attribute:reply_to_label' => 'Reply to (label)~~',
|
||||
'Class:ActionEmail/Attribute:reply_to_label+' => 'Reply to display name will be sent into the email header~~',
|
||||
'Class:ActionEmail/Attribute:to' => 'A',
|
||||
'Class:ActionEmail/Attribute:to+' => '',
|
||||
'Class:ActionEmail/Attribute:cc' => 'Copie',
|
||||
|
||||
@@ -503,10 +503,14 @@ Dict::Add('HU HU', 'Hungarian', 'Magyar', array(
|
||||
'Class:ActionEmail+' => '',
|
||||
'Class:ActionEmail/Attribute:test_recipient' => 'Teszt címzett',
|
||||
'Class:ActionEmail/Attribute:test_recipient+' => '',
|
||||
'Class:ActionEmail/Attribute:from' => 'Feladó',
|
||||
'Class:ActionEmail/Attribute:from+' => '',
|
||||
'Class:ActionEmail/Attribute:reply_to' => 'Válasz',
|
||||
'Class:ActionEmail/Attribute:reply_to+' => '',
|
||||
'Class:ActionEmail/Attribute:from' => 'Feladó~~',
|
||||
'Class:ActionEmail/Attribute:from+' => '~~',
|
||||
'Class:ActionEmail/Attribute:from_label' => 'From (label)~~',
|
||||
'Class:ActionEmail/Attribute:from_label+' => 'Sender display name will be sent into the email header~~',
|
||||
'Class:ActionEmail/Attribute:reply_to' => 'Válasz~~',
|
||||
'Class:ActionEmail/Attribute:reply_to+' => '~~',
|
||||
'Class:ActionEmail/Attribute:reply_to_label' => 'Reply to (label)~~',
|
||||
'Class:ActionEmail/Attribute:reply_to_label+' => 'Reply to display name will be sent into the email header~~',
|
||||
'Class:ActionEmail/Attribute:to' => 'Címzett',
|
||||
'Class:ActionEmail/Attribute:to+' => '',
|
||||
'Class:ActionEmail/Attribute:cc' => 'Másolatot kap',
|
||||
|
||||
@@ -505,10 +505,14 @@ Dict::Add('IT IT', 'Italian', 'Italiano', array(
|
||||
'Class:ActionEmail+' => '',
|
||||
'Class:ActionEmail/Attribute:test_recipient' => 'Test destinatario',
|
||||
'Class:ActionEmail/Attribute:test_recipient+' => '',
|
||||
'Class:ActionEmail/Attribute:from' => 'Da',
|
||||
'Class:ActionEmail/Attribute:from+' => '',
|
||||
'Class:ActionEmail/Attribute:reply_to' => 'Rispondi A',
|
||||
'Class:ActionEmail/Attribute:reply_to+' => '',
|
||||
'Class:ActionEmail/Attribute:from' => 'Da~~',
|
||||
'Class:ActionEmail/Attribute:from+' => '~~',
|
||||
'Class:ActionEmail/Attribute:from_label' => 'From (label)~~',
|
||||
'Class:ActionEmail/Attribute:from_label+' => 'Sender display name will be sent into the email header~~',
|
||||
'Class:ActionEmail/Attribute:reply_to' => 'Rispondi A~~',
|
||||
'Class:ActionEmail/Attribute:reply_to+' => '~~',
|
||||
'Class:ActionEmail/Attribute:reply_to_label' => 'Reply to (label)~~',
|
||||
'Class:ActionEmail/Attribute:reply_to_label+' => 'Reply to display name will be sent into the email header~~',
|
||||
'Class:ActionEmail/Attribute:to' => 'A',
|
||||
'Class:ActionEmail/Attribute:to+' => 'Destinatario dell\'email',
|
||||
'Class:ActionEmail/Attribute:cc' => 'Cc',
|
||||
|
||||
@@ -503,10 +503,14 @@ Dict::Add('JA JP', 'Japanese', '日本語', array(
|
||||
'Class:ActionEmail+' => '',
|
||||
'Class:ActionEmail/Attribute:test_recipient' => 'テストレシピ',
|
||||
'Class:ActionEmail/Attribute:test_recipient+' => '状態がテストの場合の宛先',
|
||||
'Class:ActionEmail/Attribute:from' => 'From',
|
||||
'Class:ActionEmail/Attribute:from+' => '電子メールのヘッダーに挿入されます',
|
||||
'Class:ActionEmail/Attribute:reply_to' => 'Reply to',
|
||||
'Class:ActionEmail/Attribute:reply_to+' => '電子メールのヘッダーに挿入されます',
|
||||
'Class:ActionEmail/Attribute:from' => 'From~~',
|
||||
'Class:ActionEmail/Attribute:from+' => '電子メールのヘッダーに挿入されます~~',
|
||||
'Class:ActionEmail/Attribute:from_label' => 'From (label)~~',
|
||||
'Class:ActionEmail/Attribute:from_label+' => 'Sender display name will be sent into the email header~~',
|
||||
'Class:ActionEmail/Attribute:reply_to' => 'Reply to~~',
|
||||
'Class:ActionEmail/Attribute:reply_to+' => '電子メールのヘッダーに挿入されます~~',
|
||||
'Class:ActionEmail/Attribute:reply_to_label' => 'Reply to (label)~~',
|
||||
'Class:ActionEmail/Attribute:reply_to_label+' => 'Reply to display name will be sent into the email header~~',
|
||||
'Class:ActionEmail/Attribute:to' => 'To',
|
||||
'Class:ActionEmail/Attribute:to+' => 'メールの宛先',
|
||||
'Class:ActionEmail/Attribute:cc' => 'Cc',
|
||||
|
||||
@@ -511,10 +511,14 @@ Dict::Add('NL NL', 'Dutch', 'Nederlands', array(
|
||||
'Class:ActionEmail+' => '',
|
||||
'Class:ActionEmail/Attribute:test_recipient' => 'Testontvanger',
|
||||
'Class:ActionEmail/Attribute:test_recipient+' => 'Bestemming als de status op "Test" staat',
|
||||
'Class:ActionEmail/Attribute:from' => 'Van',
|
||||
'Class:ActionEmail/Attribute:from' => 'Van (e-mail)',
|
||||
'Class:ActionEmail/Attribute:from+' => 'Wordt gebruikt in de hoofdtekst van de e-mail (headers)',
|
||||
'Class:ActionEmail/Attribute:reply_to' => 'Antwoord',
|
||||
'Class:ActionEmail/Attribute:from_label' => 'Van (label)',
|
||||
'Class:ActionEmail/Attribute:from_label+' => 'Wordt gebruikt in de hoofdtekst van de e-mail (headers)',
|
||||
'Class:ActionEmail/Attribute:reply_to' => 'Antwoord (e-mail)',
|
||||
'Class:ActionEmail/Attribute:reply_to+' => 'Wordt gebruikt in de hoofdtekst van de e-mail (headers)',
|
||||
'Class:ActionEmail/Attribute:reply_to_label' => 'Antwoord (label)',
|
||||
'Class:ActionEmail/Attribute:reply_to_label+' => 'Wordt gebruikt in de hoofdtekst van de e-mail (headers)',
|
||||
'Class:ActionEmail/Attribute:to' => 'Aan',
|
||||
'Class:ActionEmail/Attribute:to+' => 'Bestemming van de e-mail',
|
||||
'Class:ActionEmail/Attribute:cc' => 'CC',
|
||||
|
||||
@@ -505,10 +505,14 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array(
|
||||
'Class:ActionEmail+' => '',
|
||||
'Class:ActionEmail/Attribute:test_recipient' => 'Testar destinatário',
|
||||
'Class:ActionEmail/Attribute:test_recipient+' => 'Destinatário em caso o estado está definido como "Teste"',
|
||||
'Class:ActionEmail/Attribute:from' => 'De',
|
||||
'Class:ActionEmail/Attribute:from+' => 'Será enviado para o cabeçalho de email',
|
||||
'Class:ActionEmail/Attribute:reply_to' => 'Responder para',
|
||||
'Class:ActionEmail/Attribute:reply_to+' => 'Será enviado para o cabeçalho de email',
|
||||
'Class:ActionEmail/Attribute:from' => 'De~~',
|
||||
'Class:ActionEmail/Attribute:from+' => 'Será enviado para o cabeçalho de email~~',
|
||||
'Class:ActionEmail/Attribute:from_label' => 'From (label)~~',
|
||||
'Class:ActionEmail/Attribute:from_label+' => 'Sender display name will be sent into the email header~~',
|
||||
'Class:ActionEmail/Attribute:reply_to' => 'Responder para~~',
|
||||
'Class:ActionEmail/Attribute:reply_to+' => 'Será enviado para o cabeçalho de email~~',
|
||||
'Class:ActionEmail/Attribute:reply_to_label' => 'Reply to (label)~~',
|
||||
'Class:ActionEmail/Attribute:reply_to_label+' => 'Reply to display name will be sent into the email header~~',
|
||||
'Class:ActionEmail/Attribute:to' => 'Para',
|
||||
'Class:ActionEmail/Attribute:to+' => 'Destinatário para o email',
|
||||
'Class:ActionEmail/Attribute:cc' => 'CC',
|
||||
|
||||
@@ -492,10 +492,14 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Class:ActionEmail+' => '',
|
||||
'Class:ActionEmail/Attribute:test_recipient' => 'Тестовый получатель',
|
||||
'Class:ActionEmail/Attribute:test_recipient+' => 'Получатель, если уведомление в статусе "Тест"',
|
||||
'Class:ActionEmail/Attribute:from' => 'От',
|
||||
'Class:ActionEmail/Attribute:from+' => 'Будет отправлено в заголовке email',
|
||||
'Class:ActionEmail/Attribute:reply_to' => 'Ответить на',
|
||||
'Class:ActionEmail/Attribute:reply_to+' => 'Будет отправлено в заголовке email',
|
||||
'Class:ActionEmail/Attribute:from' => 'От~~',
|
||||
'Class:ActionEmail/Attribute:from+' => 'Будет отправлено в заголовке email~~',
|
||||
'Class:ActionEmail/Attribute:from_label' => 'From (label)~~',
|
||||
'Class:ActionEmail/Attribute:from_label+' => 'Sender display name will be sent into the email header~~',
|
||||
'Class:ActionEmail/Attribute:reply_to' => 'Ответить на~~',
|
||||
'Class:ActionEmail/Attribute:reply_to+' => 'Будет отправлено в заголовке email~~',
|
||||
'Class:ActionEmail/Attribute:reply_to_label' => 'Reply to (label)~~',
|
||||
'Class:ActionEmail/Attribute:reply_to_label+' => 'Reply to display name will be sent into the email header~~',
|
||||
'Class:ActionEmail/Attribute:to' => 'Кому',
|
||||
'Class:ActionEmail/Attribute:to+' => 'Получатель email',
|
||||
'Class:ActionEmail/Attribute:cc' => 'Копия',
|
||||
|
||||
@@ -502,10 +502,14 @@ Dict::Add('SK SK', 'Slovak', 'Slovenčina', array(
|
||||
'Class:ActionEmail+' => '',
|
||||
'Class:ActionEmail/Attribute:test_recipient' => 'Testovací príjemca',
|
||||
'Class:ActionEmail/Attribute:test_recipient+' => '',
|
||||
'Class:ActionEmail/Attribute:from' => 'Od',
|
||||
'Class:ActionEmail/Attribute:from+' => '',
|
||||
'Class:ActionEmail/Attribute:reply_to' => 'Odpoveď na',
|
||||
'Class:ActionEmail/Attribute:reply_to+' => '',
|
||||
'Class:ActionEmail/Attribute:from' => 'Od~~',
|
||||
'Class:ActionEmail/Attribute:from+' => '~~',
|
||||
'Class:ActionEmail/Attribute:from_label' => 'From (label)~~',
|
||||
'Class:ActionEmail/Attribute:from_label+' => 'Sender display name will be sent into the email header~~',
|
||||
'Class:ActionEmail/Attribute:reply_to' => 'Odpoveď na~~',
|
||||
'Class:ActionEmail/Attribute:reply_to+' => '~~',
|
||||
'Class:ActionEmail/Attribute:reply_to_label' => 'Reply to (label)~~',
|
||||
'Class:ActionEmail/Attribute:reply_to_label+' => 'Reply to display name will be sent into the email header~~',
|
||||
'Class:ActionEmail/Attribute:to' => 'Komu',
|
||||
'Class:ActionEmail/Attribute:to+' => '',
|
||||
'Class:ActionEmail/Attribute:cc' => 'Kópia',
|
||||
|
||||
@@ -513,10 +513,14 @@ Dict::Add('TR TR', 'Turkish', 'Türkçe', array(
|
||||
'Class:ActionEmail+' => '',
|
||||
'Class:ActionEmail/Attribute:test_recipient' => 'Test alıcısı',
|
||||
'Class:ActionEmail/Attribute:test_recipient+' => 'Durumu "Test" olması durumundaki alıcı',
|
||||
'Class:ActionEmail/Attribute:from' => 'Kimden',
|
||||
'Class:ActionEmail/Attribute:from+' => 'e-posta başlığında gönderilecek',
|
||||
'Class:ActionEmail/Attribute:reply_to' => 'Yanıtla',
|
||||
'Class:ActionEmail/Attribute:reply_to+' => 'e-posta başlığında gönderilecek',
|
||||
'Class:ActionEmail/Attribute:from' => 'Kimden~~',
|
||||
'Class:ActionEmail/Attribute:from+' => 'e-posta başlığında gönderilecek~~',
|
||||
'Class:ActionEmail/Attribute:from_label' => 'From (label)~~',
|
||||
'Class:ActionEmail/Attribute:from_label+' => 'Sender display name will be sent into the email header~~',
|
||||
'Class:ActionEmail/Attribute:reply_to' => 'Yanıtla~~',
|
||||
'Class:ActionEmail/Attribute:reply_to+' => 'e-posta başlığında gönderilecek~~',
|
||||
'Class:ActionEmail/Attribute:reply_to_label' => 'Reply to (label)~~',
|
||||
'Class:ActionEmail/Attribute:reply_to_label+' => 'Reply to display name will be sent into the email header~~',
|
||||
'Class:ActionEmail/Attribute:to' => 'Kime',
|
||||
'Class:ActionEmail/Attribute:to+' => 'E-posta alıcısı',
|
||||
'Class:ActionEmail/Attribute:cc' => 'Kopya',
|
||||
|
||||
@@ -504,10 +504,14 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', array(
|
||||
'Class:ActionEmail+' => '',
|
||||
'Class:ActionEmail/Attribute:test_recipient' => '测试收件人',
|
||||
'Class:ActionEmail/Attribute:test_recipient+' => 'Detination in case status is set to "Test"',
|
||||
'Class:ActionEmail/Attribute:from' => '发件人',
|
||||
'Class:ActionEmail/Attribute:from+' => 'Will be sent into the email header',
|
||||
'Class:ActionEmail/Attribute:reply_to' => '回复到',
|
||||
'Class:ActionEmail/Attribute:reply_to+' => 'Will be sent into the email header',
|
||||
'Class:ActionEmail/Attribute:from' => '发件人~~',
|
||||
'Class:ActionEmail/Attribute:from+' => 'Will be sent into the email header~~',
|
||||
'Class:ActionEmail/Attribute:from_label' => 'From (label)~~',
|
||||
'Class:ActionEmail/Attribute:from_label+' => 'Sender display name will be sent into the email header~~',
|
||||
'Class:ActionEmail/Attribute:reply_to' => '回复到~~',
|
||||
'Class:ActionEmail/Attribute:reply_to+' => 'Will be sent into the email header~~',
|
||||
'Class:ActionEmail/Attribute:reply_to_label' => 'Reply to (label)~~',
|
||||
'Class:ActionEmail/Attribute:reply_to_label+' => 'Reply to display name will be sent into the email header~~',
|
||||
'Class:ActionEmail/Attribute:to' => '收件人',
|
||||
'Class:ActionEmail/Attribute:to+' => 'Destination of the email',
|
||||
'Class:ActionEmail/Attribute:cc' => '抄送',
|
||||
|
||||
@@ -231,6 +231,8 @@
|
||||
css = $.extend({}, $.blockUI.defaults.css, opts.css || {});
|
||||
if (opts.onOverlayClick)
|
||||
opts.overlayCSS.cursor = 'pointer';
|
||||
if (opts.enableValidation)
|
||||
opts.overlayCSS.cursor = 'not-allowed';
|
||||
|
||||
themedCSS = $.extend({}, $.blockUI.defaults.themedCSS, opts.themedCSS || {});
|
||||
msg = msg === undefined ? opts.message : msg;
|
||||
@@ -292,7 +294,12 @@
|
||||
s = '<div class="blockUI ' + opts.blockMsgClass + ' blockPage" style="z-index:'+(z+10)+';display:none;position:fixed"></div>';
|
||||
}
|
||||
else {
|
||||
s = '<div class="blockUI ' + opts.blockMsgClass + ' blockElement" style="z-index:'+(z+10)+';display:none;position:absolute"></div>';
|
||||
if (opts.enableValidation) {
|
||||
s = '<div class="blockUI blockElement" style="z-index:'+(z+10)+';display:none;position:absolute"></div>';
|
||||
}
|
||||
else{
|
||||
s = '<div class="blockUI '+opts.blockMsgClass+' blockElement" style="z-index:'+(z+10)+';display:none;position:absolute"></div>';
|
||||
}
|
||||
}
|
||||
lyr3 = $(s);
|
||||
|
||||
|
||||
@@ -90,7 +90,7 @@ $(document).ready(function () {
|
||||
|
||||
|
||||
/**
|
||||
* Our custom handlers chould run only if clicking on somewhere without event already attached !
|
||||
* Our custom handlers should run only if clicking on somewhere without event already attached !
|
||||
* @param $eventTarget
|
||||
* @returns {boolean} true if our custom handler shouldn't be run
|
||||
*/
|
||||
@@ -101,12 +101,18 @@ $(document).ready(function () {
|
||||
if ($eventTarget.is("a, button")) {
|
||||
return true;
|
||||
}
|
||||
if ($eventTarget.is(".fas, i.fa")) { // Font Awesome buttons
|
||||
return true;
|
||||
}
|
||||
if ($eventTarget.parent().is('a, button')) {
|
||||
return true;
|
||||
}
|
||||
if ($eventTarget.is("input, select, option")) {
|
||||
return true;
|
||||
}
|
||||
if ($eventTarget.parent().is(".selectize-control,.selectize-input")) {
|
||||
return true;
|
||||
}
|
||||
if ($eventTarget.is("img")) { // too hard to determine if an event handler is attached so excluding all !
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -388,13 +388,12 @@ function ToggleField(value, field_id) {
|
||||
*/
|
||||
function BlockField(field_id, bBlocked) {
|
||||
if (bBlocked) {
|
||||
$('#'+field_id).block({message: ' ** disabled ** '});
|
||||
$('#'+field_id).block({message: ' ** disabled ** ', enableValidation : true});
|
||||
}
|
||||
else {
|
||||
$('#'+field_id).unblock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates (enables/disables) a "duration" field
|
||||
*/
|
||||
|
||||
@@ -22,19 +22,18 @@
|
||||
* @copyright Copyright (C) 2010-2018 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
class CheckResult
|
||||
{
|
||||
class CheckResult {
|
||||
// Severity levels
|
||||
const ERROR = 0;
|
||||
const WARNING = 1;
|
||||
const INFO = 2;
|
||||
const TRACE = 3; // for log purposes : replace old SetupLog::Log calls
|
||||
|
||||
public $iSeverity;
|
||||
public $sLabel;
|
||||
public $sDescription;
|
||||
|
||||
public function __construct($iSeverity, $sLabel, $sDescription = '')
|
||||
{
|
||||
public function __construct($iSeverity, $sLabel, $sDescription = '') {
|
||||
$this->iSeverity = $iSeverity;
|
||||
$this->sLabel = $sLabel;
|
||||
$this->sDescription = $sDescription;
|
||||
@@ -44,28 +43,29 @@ class CheckResult
|
||||
* @return string
|
||||
* @since 2.8.0 N°2214
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
public function __toString(): string {
|
||||
$sPrintDesc = (empty($this->sDescription)) ? '' : " ({$this->sDescription})";
|
||||
|
||||
return "{$this->sLabel}$sPrintDesc";
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \CheckResult[] $aResults
|
||||
* @param string[] $aCheckResultSeverities list of CheckResult object severities to keep
|
||||
*
|
||||
* @return \CheckResult[] only elements that are error (iSeverity===ERROR)
|
||||
* @return \CheckResult[] only elements that have one of the passed severity
|
||||
*
|
||||
* @since 2.8.0 N°2214
|
||||
*/
|
||||
public static function KeepOnlyErrors($aResults)
|
||||
{
|
||||
public static function FilterCheckResultArray(array $aResults, array $aCheckResultSeverities): array {
|
||||
return array_filter($aResults,
|
||||
static function ($v)
|
||||
{
|
||||
if ($v->iSeverity === CheckResult::ERROR) {
|
||||
static function ($v) use ($aCheckResultSeverities) {
|
||||
if (in_array($v->iSeverity, $aCheckResultSeverities, true)) {
|
||||
return $v;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
ARRAY_FILTER_USE_BOTH);
|
||||
}
|
||||
|
||||
@@ -77,9 +77,8 @@ class CheckResult
|
||||
*
|
||||
* @since 2.8.0 N°2214
|
||||
*/
|
||||
public static function FromObjectsToStrings($aResults)
|
||||
{
|
||||
return array_map(function ($value) {
|
||||
public static function FromObjectsToStrings(array $aResults): array {
|
||||
return array_map(static function ($value) {
|
||||
return $value->__toString();
|
||||
}, $aResults);
|
||||
}
|
||||
@@ -117,16 +116,27 @@ class SetupUtils
|
||||
* <li>...
|
||||
* </ul>
|
||||
*
|
||||
* @internal SetupPage $oP The page used only for its 'log' method
|
||||
* @return CheckResult[]
|
||||
*
|
||||
* @uses SetupPage $oP The page used only for its 'log' method
|
||||
* @uses utils::IsModeCLI() to disable following checks :
|
||||
* <ul>
|
||||
* <li>php.ini option : file_uploads
|
||||
* <li>Temp upload dir valid
|
||||
* <li>php.ini option : upload_max_filesize
|
||||
* <li>php.ini option : max_file_uploads
|
||||
* <li>php.ini option : upload_max_filesize, post_max_size
|
||||
* <li>php.ini option : session.save_handler
|
||||
* </ul>
|
||||
*
|
||||
* @since 2.8.0 N°2214 disable some checks when in CLI mode
|
||||
* @since 2.8.0 N°2214 replace SetupLog::Ok calls by CheckResult::TRACE
|
||||
*/
|
||||
public static function CheckPhpAndExtensions()
|
||||
{
|
||||
public static function CheckPhpAndExtensions() {
|
||||
$aResult = array();
|
||||
|
||||
// For log file(s)
|
||||
if (!is_dir(APPROOT.'log'))
|
||||
{
|
||||
if (!is_dir(APPROOT.'log')) {
|
||||
@mkdir(APPROOT.'log');
|
||||
}
|
||||
|
||||
@@ -220,74 +230,74 @@ class SetupUtils
|
||||
{
|
||||
$sPhpIniFile = php_ini_loaded_file();
|
||||
// Other included/scanned files
|
||||
if ($sFileList = php_ini_scanned_files())
|
||||
{
|
||||
if (strlen($sFileList) > 0)
|
||||
{
|
||||
if ($sFileList = php_ini_scanned_files()) {
|
||||
if (strlen($sFileList) > 0) {
|
||||
$aFiles = explode(',', $sFileList);
|
||||
|
||||
foreach ($aFiles as $sFile)
|
||||
{
|
||||
foreach ($aFiles as $sFile) {
|
||||
$sPhpIniFile .= ', '.trim($sFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
SetupLog::Ok("Info - php.ini file(s): '$sPhpIniFile'");
|
||||
$aResult[] = new CheckResult(CheckResult::TRACE, "Info - php.ini file(s): '$sPhpIniFile'");
|
||||
}
|
||||
|
||||
if (!ini_get('file_uploads'))
|
||||
{
|
||||
$aResult[] = new CheckResult(CheckResult::ERROR, "Files upload is not allowed on this server (file_uploads = ".ini_get('file_uploads').").");
|
||||
if (!utils::IsModeCLI() && !ini_get('file_uploads')) {
|
||||
$aResult[] = new CheckResult(CheckResult::ERROR,
|
||||
"Files upload is not allowed on this server (file_uploads = ".ini_get('file_uploads').").");
|
||||
}
|
||||
|
||||
$sUploadTmpDir = self::GetUploadTmpDir();
|
||||
if (empty($sUploadTmpDir))
|
||||
{
|
||||
$sUploadTmpDir = '/tmp';
|
||||
$aResult[] = new CheckResult(CheckResult::WARNING, "Temporary directory for files upload is not defined (upload_tmp_dir), assuming that $sUploadTmpDir is used.");
|
||||
}
|
||||
// check that the upload directory is indeed writable from PHP
|
||||
if (!empty($sUploadTmpDir))
|
||||
{
|
||||
if (!file_exists($sUploadTmpDir))
|
||||
{
|
||||
$aResult[] = new CheckResult(CheckResult::ERROR, "Temporary directory for files upload ($sUploadTmpDir) does not exist or cannot be read by PHP.");
|
||||
if (!utils::IsModeCLI()) {
|
||||
$sUploadTmpDir = self::GetUploadTmpDir();
|
||||
if (empty($sUploadTmpDir)) {
|
||||
$sUploadTmpDir = '/tmp';
|
||||
$aResult[] = new CheckResult(CheckResult::WARNING,
|
||||
"Temporary directory for files upload is not defined (upload_tmp_dir), assuming that $sUploadTmpDir is used.");
|
||||
}
|
||||
else if (!is_writable($sUploadTmpDir))
|
||||
{
|
||||
$aResult[] = new CheckResult(CheckResult::ERROR, "Temporary directory for files upload ($sUploadTmpDir) is not writable.");
|
||||
}
|
||||
else
|
||||
{
|
||||
SetupLog::Ok("Info - Temporary directory for files upload ($sUploadTmpDir) is writable.");
|
||||
// check that the upload directory is indeed writable from PHP
|
||||
if (!empty($sUploadTmpDir)) {
|
||||
if (!file_exists($sUploadTmpDir)) {
|
||||
$aResult[] = new CheckResult(CheckResult::ERROR,
|
||||
"Temporary directory for files upload ($sUploadTmpDir) does not exist or cannot be read by PHP.");
|
||||
}
|
||||
else {
|
||||
if (!is_writable($sUploadTmpDir)) {
|
||||
$aResult[] = new CheckResult(CheckResult::ERROR,
|
||||
"Temporary directory for files upload ($sUploadTmpDir) is not writable.");
|
||||
}
|
||||
else {
|
||||
$aResult[] = new CheckResult(CheckResult::TRACE,
|
||||
"Info - Temporary directory for files upload ($sUploadTmpDir) is writable.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!ini_get('upload_max_filesize'))
|
||||
{
|
||||
$aResult[] = new CheckResult(CheckResult::ERROR, "File upload is not allowed on this server (upload_max_filesize = ".ini_get('upload_max_filesize').").");
|
||||
if (!utils::IsModeCLI() && !ini_get('upload_max_filesize')) {
|
||||
$aResult[] = new CheckResult(CheckResult::ERROR,
|
||||
"File upload is not allowed on this server (upload_max_filesize = ".ini_get('upload_max_filesize').").");
|
||||
}
|
||||
|
||||
$iMaxFileUploads = ini_get('max_file_uploads');
|
||||
if (!empty($iMaxFileUploads) && ($iMaxFileUploads < 1))
|
||||
{
|
||||
$aResult[] = new CheckResult(CheckResult::ERROR, "File upload is not allowed on this server (max_file_uploads = ".ini_get('max_file_uploads').").");
|
||||
if (!utils::IsModeCLI() && !empty($iMaxFileUploads) && ($iMaxFileUploads < 1)) {
|
||||
$aResult[] = new CheckResult(CheckResult::ERROR,
|
||||
"File upload is not allowed on this server (max_file_uploads = ".ini_get('max_file_uploads').").");
|
||||
}
|
||||
|
||||
$iMaxUploadSize = utils::ConvertToBytes(ini_get('upload_max_filesize'));
|
||||
$iMaxPostSize = utils::ConvertToBytes(ini_get('post_max_size'));
|
||||
if (!utils::IsModeCLI()) {
|
||||
$iMaxUploadSize = utils::ConvertToBytes(ini_get('upload_max_filesize'));
|
||||
$iMaxPostSize = utils::ConvertToBytes(ini_get('post_max_size'));
|
||||
|
||||
if ($iMaxPostSize <= $iMaxUploadSize)
|
||||
{
|
||||
$aResult[] = new CheckResult(CheckResult::WARNING, "post_max_size (".ini_get('post_max_size').") in php.ini should be strictly greater than upload_max_filesize (".ini_get('upload_max_filesize').") otherwise you cannot upload files of the maximum size.");
|
||||
if ($iMaxPostSize <= $iMaxUploadSize) {
|
||||
$aResult[] = new CheckResult(CheckResult::WARNING,
|
||||
"post_max_size (".ini_get('post_max_size').") in php.ini should be strictly greater than upload_max_filesize (".ini_get('upload_max_filesize').") otherwise you cannot upload files of the maximum size.");
|
||||
}
|
||||
|
||||
$aResult[] = new CheckResult(CheckResult::TRACE, "Info - upload_max_filesize: ".ini_get('upload_max_filesize'));
|
||||
$aResult[] = new CheckResult(CheckResult::TRACE, "Info - post_max_size: ".ini_get('post_max_size'));
|
||||
$aResult[] = new CheckResult(CheckResult::TRACE, "Info - max_file_uploads: ".ini_get('max_file_uploads'));
|
||||
}
|
||||
|
||||
|
||||
SetupLog::Ok("Info - upload_max_filesize: ".ini_get('upload_max_filesize'));
|
||||
SetupLog::Ok("Info - post_max_size: ".ini_get('post_max_size'));
|
||||
SetupLog::Ok("Info - max_file_uploads: ".ini_get('max_file_uploads'));
|
||||
|
||||
// Check some more ini settings here, needed for file upload
|
||||
$sMemoryLimit = trim(ini_get('memory_limit'));
|
||||
if (empty($sMemoryLimit))
|
||||
@@ -302,13 +312,12 @@ class SetupUtils
|
||||
// Check that the limit will allow us to load the data
|
||||
//
|
||||
$iMemoryLimit = utils::ConvertToBytes($sMemoryLimit);
|
||||
if (!utils::IsMemoryLimitOk($iMemoryLimit, self::MIN_MEMORY_LIMIT))
|
||||
{
|
||||
$aResult[] = new CheckResult(CheckResult::ERROR, "memory_limit ($iMemoryLimit) is too small, the minimum value to run the application is ".self::MIN_MEMORY_LIMIT.".");
|
||||
if (!utils::IsMemoryLimitOk($iMemoryLimit, self::MIN_MEMORY_LIMIT)) {
|
||||
$aResult[] = new CheckResult(CheckResult::ERROR,
|
||||
"memory_limit ($iMemoryLimit) is too small, the minimum value to run the application is ".self::MIN_MEMORY_LIMIT.".");
|
||||
}
|
||||
else
|
||||
{
|
||||
SetupLog::Ok("Info - memory_limit is $iMemoryLimit, ok.");
|
||||
else {
|
||||
$aResult[] = new CheckResult(CheckResult::TRACE, "Info - memory_limit is $iMemoryLimit, ok.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -326,13 +335,12 @@ class SetupUtils
|
||||
$aOk[] = "Suhosin extension detected (version $sSuhosinVersion).";
|
||||
|
||||
$iGetMaxValueLength = ini_get('suhosin.get.max_value_length');
|
||||
if ($iGetMaxValueLength < self::SUHOSIN_GET_MAX_VALUE_LENGTH)
|
||||
{
|
||||
$aResult[] = new CheckResult(CheckResult::WARNING, "suhosin.get.max_value_length ($iGetMaxValueLength) is too small, the minimum value recommended to run the application is ".self::SUHOSIN_GET_MAX_VALUE_LENGTH.".");
|
||||
if ($iGetMaxValueLength < self::SUHOSIN_GET_MAX_VALUE_LENGTH) {
|
||||
$aResult[] = new CheckResult(CheckResult::WARNING,
|
||||
"suhosin.get.max_value_length ($iGetMaxValueLength) is too small, the minimum value recommended to run the application is ".self::SUHOSIN_GET_MAX_VALUE_LENGTH.".");
|
||||
}
|
||||
else
|
||||
{
|
||||
SetupLog::Ok("Info - suhosin.get.max_value_length = $iGetMaxValueLength, ok.");
|
||||
else {
|
||||
$aResult[] = new CheckResult(CheckResult::TRACE, "Info - suhosin.get.max_value_length = $iGetMaxValueLength, ok.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -340,79 +348,80 @@ class SetupUtils
|
||||
{
|
||||
$sPhpIniFile = php_ini_loaded_file();
|
||||
// Other included/scanned files
|
||||
if ($sFileList = php_ini_scanned_files())
|
||||
{
|
||||
if (strlen($sFileList) > 0)
|
||||
{
|
||||
if ($sFileList = php_ini_scanned_files()) {
|
||||
if (strlen($sFileList) > 0) {
|
||||
$aFiles = explode(',', $sFileList);
|
||||
|
||||
foreach ($aFiles as $sFile)
|
||||
{
|
||||
foreach ($aFiles as $sFile) {
|
||||
$sPhpIniFile .= ', '.trim($sFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
$aResult[] = new CheckResult(CheckResult::INFO, "Loaded php.ini files: $sPhpIniFile");
|
||||
$aResult[] = new CheckResult(CheckResult::INFO, "Loaded php.ini files: $sPhpIniFile");
|
||||
}
|
||||
|
||||
// Check the configuration of the sessions persistence, since this is critical for the authentication
|
||||
if (ini_get('session.save_handler') == 'files')
|
||||
{
|
||||
$sSavePath = ini_get('session.save_path');
|
||||
SetupLog::Ok("Info - session.save_path is: '$sSavePath'.");
|
||||
if (!utils::IsModeCLI()) {
|
||||
if (ini_get('session.save_handler') == 'files') {
|
||||
$sSavePath = ini_get('session.save_path');
|
||||
$aResult[] = new CheckResult(CheckResult::TRACE, "Info - session.save_path is: '$sSavePath'.");
|
||||
|
||||
// According to the PHP documentation, the format can be /path/where/to_save_sessions or "N;/path/where/to_save_sessions" or "N;MODE;/path/where/to_save_sessions"
|
||||
$sSavePath = ltrim(rtrim($sSavePath, '"'), '"'); // remove surrounding quotes (if any)
|
||||
// According to the PHP documentation, the format can be /path/where/to_save_sessions or "N;/path/where/to_save_sessions" or "N;MODE;/path/where/to_save_sessions"
|
||||
$sSavePath = ltrim(rtrim($sSavePath, '"'), '"'); // remove surrounding quotes (if any)
|
||||
|
||||
if (!empty($sSavePath))
|
||||
{
|
||||
if (($iPos = strrpos($sSavePath, ';', 0)) !== false)
|
||||
{
|
||||
// The actual path is after the last semicolon
|
||||
$sSavePath = substr($sSavePath, $iPos+1);
|
||||
if (!empty($sSavePath)) {
|
||||
if (($iPos = strrpos($sSavePath, ';', 0)) !== false) {
|
||||
// The actual path is after the last semicolon
|
||||
$sSavePath = substr($sSavePath, $iPos + 1);
|
||||
}
|
||||
if (!is_writable($sSavePath)) {
|
||||
$aResult[] = new CheckResult(CheckResult::ERROR,
|
||||
"The value for session.save_path ($sSavePath) is not writable for the web server. Make sure that PHP can actually save session variables. (Refer to the PHP documentation: http://php.net/manual/en/session.configuration.php#ini.session.save-path)");
|
||||
}
|
||||
else {
|
||||
$aResult[] = new CheckResult(CheckResult::INFO,
|
||||
"The value for session.save_path ($sSavePath) is writable for the web server.");
|
||||
}
|
||||
}
|
||||
if (!is_writable($sSavePath))
|
||||
{
|
||||
$aResult[] = new CheckResult(CheckResult::ERROR, "The value for session.save_path ($sSavePath) is not writable for the web server. Make sure that PHP can actually save session variables. (Refer to the PHP documentation: http://php.net/manual/en/session.configuration.php#ini.session.save-path)");
|
||||
}
|
||||
else
|
||||
{
|
||||
$aResult[] = new CheckResult(CheckResult::INFO, "The value for session.save_path ($sSavePath) is writable for the web server.");
|
||||
else {
|
||||
$aResult[] = new CheckResult(CheckResult::WARNING,
|
||||
"Empty path for session.save_path. Make sure that PHP can actually save session variables. (Refer to the PHP documentation: http://php.net/manual/en/session.configuration.php#ini.session.save-path)");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$aResult[] = new CheckResult(CheckResult::WARNING, "Empty path for session.save_path. Make sure that PHP can actually save session variables. (Refer to the PHP documentation: http://php.net/manual/en/session.configuration.php#ini.session.save-path)");
|
||||
else {
|
||||
$aResult[] = new CheckResult(CheckResult::INFO,
|
||||
"session.save_handler is: '".ini_get('session.save_handler')."' (different from 'files').");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$aResult[] = new CheckResult(CheckResult::INFO, "session.save_handler is: '".ini_get('session.save_handler')."' (different from 'files').");
|
||||
}
|
||||
|
||||
return $aResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call the platform checks. If those checks return CheckResult::ERROR, then output and log them, then exit. Otherwise just return.
|
||||
*
|
||||
* @param \CLIPage $oCliPage
|
||||
* @param int $iExitCode
|
||||
*
|
||||
* @since 2.8.0 N°2214
|
||||
* @uses CheckPhpAndExtensions
|
||||
* @uses \CheckResult::FilterCheckResultArray()
|
||||
* @uses \CLIPage::output()
|
||||
* @uses \IssueLog::Error()
|
||||
* @uses \exit()
|
||||
*
|
||||
* @since 2.8.0 N°2214 Add PHP version checks in CLI scripts
|
||||
*/
|
||||
public static function CheckPhpAndExtensionsForCli($oCliPage, $iExitCode = -1)
|
||||
{
|
||||
public static function CheckPhpAndExtensionsForCli($oCliPage, $iExitCode = -1) {
|
||||
$aPhpCheckResults = self::CheckPhpAndExtensions();
|
||||
$aPhpCheckErrors = CheckResult::KeepOnlyErrors($aPhpCheckResults);
|
||||
if (empty($aPhpCheckErrors))
|
||||
{
|
||||
$aPhpCheckErrors = CheckResult::FilterCheckResultArray($aPhpCheckResults, [CheckResult::ERROR]);
|
||||
if (empty($aPhpCheckErrors)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$sMessageTitle = 'Error: PHP minimum requirements are not met !';
|
||||
$oCliPage->p($sMessageTitle);
|
||||
$aPhpCheckErrorsForPrint = CheckResult::FromObjectsToStrings($aPhpCheckErrors);
|
||||
foreach ($aPhpCheckErrorsForPrint as $sError)
|
||||
{
|
||||
foreach ($aPhpCheckErrorsForPrint as $sError) {
|
||||
$oCliPage->p(' * '.$sError);
|
||||
}
|
||||
$oCliPage->output();
|
||||
@@ -426,23 +435,21 @@ class SetupUtils
|
||||
|
||||
/**
|
||||
* @param CheckResult[] $aResult checks log
|
||||
*
|
||||
* @since 2.8.0 N°2214 replace SetupLog::Log calls by CheckResult::TRACE
|
||||
*/
|
||||
private static function CheckPhpVersion(&$aResult)
|
||||
{
|
||||
SetupLog::Ok('Info - CheckPHPVersion');
|
||||
private static function CheckPhpVersion(array &$aResult) {
|
||||
$aResult[] = new CheckResult(CheckResult::TRACE, 'Info - CheckPHPVersion');
|
||||
$sPhpVersion = phpversion();
|
||||
|
||||
if (version_compare($sPhpVersion, self::PHP_MIN_VERSION, '>='))
|
||||
{
|
||||
if (version_compare($sPhpVersion, self::PHP_MIN_VERSION, '>=')) {
|
||||
$aResult[] = new CheckResult(CheckResult::INFO,
|
||||
"The current PHP Version (".$sPhpVersion.") is greater than the minimum version required to run ".ITOP_APPLICATION.", which is (".self::PHP_MIN_VERSION.")");
|
||||
|
||||
|
||||
$sPhpNextMinVersion = self::PHP_NEXT_MIN_VERSION; // mandatory before PHP 5.5 (arbitrary expressions), keeping compat because we're in the setup !
|
||||
if (!empty($sPhpNextMinVersion))
|
||||
{
|
||||
if (version_compare($sPhpVersion, self::PHP_NEXT_MIN_VERSION, '>='))
|
||||
{
|
||||
if (!empty($sPhpNextMinVersion)) {
|
||||
if (version_compare($sPhpVersion, self::PHP_NEXT_MIN_VERSION, '>=')) {
|
||||
$aResult[] = new CheckResult(CheckResult::INFO,
|
||||
"The current PHP Version (".$sPhpVersion.") is greater than the minimum version required to run next ".ITOP_APPLICATION." release, which is (".self::PHP_NEXT_MIN_VERSION.")");
|
||||
}
|
||||
@@ -468,30 +475,28 @@ class SetupUtils
|
||||
|
||||
/**
|
||||
* Check that the selected modules meet their dependencies
|
||||
*
|
||||
* @param $sSourceDir
|
||||
* @param $sExtensionDir
|
||||
* @param $aSelectedModules
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 2.8.0 N°2214 replace SetupLog::Log calls by CheckResult::TRACE
|
||||
*/
|
||||
public static function CheckSelectedModules($sSourceDir, $sExtensionDir, $aSelectedModules)
|
||||
{
|
||||
public static function CheckSelectedModules($sSourceDir, $sExtensionDir, $aSelectedModules) {
|
||||
$aResult = array();
|
||||
SetupLog::Ok('Info - CheckSelectedModules');
|
||||
|
||||
$aDirsToScan = array(APPROOT.$sSourceDir);
|
||||
$sExtensionsPath = APPROOT.$sExtensionDir;
|
||||
if (is_dir($sExtensionsPath))
|
||||
{
|
||||
if (is_dir($sExtensionsPath)) {
|
||||
// if the extensions dir exists, scan it for additional modules as well
|
||||
$aDirsToScan[] = $sExtensionsPath;
|
||||
}
|
||||
require_once(APPROOT.'setup/modulediscovery.class.inc.php');
|
||||
try
|
||||
{
|
||||
try {
|
||||
ModuleDiscovery::GetAvailableModules($aDirsToScan, true, $aSelectedModules);
|
||||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
} catch (Exception $e) {
|
||||
$aResult[] = new CheckResult(CheckResult::ERROR, $e->getMessage());
|
||||
}
|
||||
return $aResult;
|
||||
@@ -499,25 +504,25 @@ class SetupUtils
|
||||
|
||||
/**
|
||||
* Check that the backup could be executed
|
||||
*
|
||||
* @param $sDBBackupPath
|
||||
* @param $sMySQLBinDir
|
||||
* @return array An array of CheckResults objects
|
||||
* @internal param Page $oP The page used only for its 'log' method
|
||||
*
|
||||
* @return \CheckResult[] An array of CheckResults objects
|
||||
*
|
||||
* @since 2.8.0 N°2214 replace SetupLog::Log calls by CheckResult::TRACE
|
||||
*/
|
||||
public static function CheckBackupPrerequisites($sDBBackupPath, $sMySQLBinDir = null)
|
||||
{
|
||||
public static function CheckBackupPrerequisites($sDBBackupPath, $sMySQLBinDir = null) {
|
||||
$aResult = array();
|
||||
SetupLog::Ok('Info - CheckBackupPrerequisites');
|
||||
$aResult[] = new CheckResult(CheckResult::TRACE, 'Info - CheckBackupPrerequisites');
|
||||
|
||||
// zip extension
|
||||
//
|
||||
if (!extension_loaded('phar'))
|
||||
{
|
||||
if (!extension_loaded('phar')) {
|
||||
$sMissingExtensionLink = "<a href=\"http://www.php.net/manual/en/book.phar.php\" target=\"_blank\">zip</a>";
|
||||
$aResult[] = new CheckResult(CheckResult::ERROR, "Missing PHP extension: phar", $sMissingExtensionLink);
|
||||
}
|
||||
if (!extension_loaded('zlib'))
|
||||
{
|
||||
if (!extension_loaded('zlib')) {
|
||||
$sMissingExtensionLink = "<a href=\"http://www.php.net/manual/en/book.zlib.php\" target=\"_blank\">zip</a>";
|
||||
$aResult[] = new CheckResult(CheckResult::ERROR, "Missing PHP extension: zlib", $sMissingExtensionLink);
|
||||
}
|
||||
@@ -525,25 +530,21 @@ class SetupUtils
|
||||
// availability of exec()
|
||||
//
|
||||
$aDisabled = explode(', ', ini_get('disable_functions'));
|
||||
SetupLog::Ok('Info - PHP functions disabled: '.implode(', ', $aDisabled));
|
||||
if (in_array('exec', $aDisabled))
|
||||
{
|
||||
$aResult[] = new CheckResult(CheckResult::TRACE, 'Info - PHP functions disabled: '.implode(', ', $aDisabled));
|
||||
if (in_array('exec', $aDisabled)) {
|
||||
$aResult[] = new CheckResult(CheckResult::ERROR, "The PHP exec() function has been disabled on this server");
|
||||
}
|
||||
|
||||
// availability of mysqldump
|
||||
if (empty($sMySQLBinDir) && null != MetaModel::GetConfig())
|
||||
{
|
||||
if (empty($sMySQLBinDir) && null != MetaModel::GetConfig()) {
|
||||
$sMySQLBinDir = MetaModel::GetConfig()->GetModuleSetting('itop-backup', 'mysql_bindir', '');
|
||||
}
|
||||
|
||||
if (empty($sMySQLBinDir))
|
||||
{
|
||||
if (empty($sMySQLBinDir)) {
|
||||
$sMySQLDump = 'mysqldump';
|
||||
}
|
||||
else
|
||||
{
|
||||
SetupLog::Ok('Info - Found mysql_bindir: '.$sMySQLBinDir);
|
||||
else {
|
||||
$aResult[] = new CheckResult(CheckResult::TRACE, 'Info - Found mysql_bindir: '.$sMySQLBinDir);
|
||||
$sMySQLDump = '"'.$sMySQLBinDir.'/mysqldump"';
|
||||
}
|
||||
$sCommand = "$sMySQLDump -V 2>&1";
|
||||
@@ -555,27 +556,25 @@ class SetupUtils
|
||||
{
|
||||
$aResult[] = new CheckResult(CheckResult::INFO, "mysqldump is present: Ok.");
|
||||
}
|
||||
elseif ($iRetCode == 1)
|
||||
{
|
||||
elseif ($iRetCode == 1) {
|
||||
// Unfortunately $aOutput is not really usable since we don't know its encoding (character set)
|
||||
$aResult[] = new CheckResult(CheckResult::ERROR, "mysqldump could not be found. Please make sure it is installed and in the path.");
|
||||
$aResult[] = new CheckResult(CheckResult::ERROR,
|
||||
"mysqldump could not be found. Please make sure it is installed and in the path.");
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
// Unfortunately $aOutput is not really usable since we don't know its encoding (character set)
|
||||
$aResult[] = new CheckResult(CheckResult::ERROR, "mysqldump could not be executed (retcode=$iRetCode): Please make sure it is installed and " . (empty($sMySQLBinDir) ? "in the path" : "located at : $sMySQLDump"));
|
||||
$aResult[] = new CheckResult(CheckResult::ERROR,
|
||||
"mysqldump could not be executed (retcode=$iRetCode): Please make sure it is installed and ".(empty($sMySQLBinDir) ? "in the path" : "located at : $sMySQLDump"));
|
||||
}
|
||||
foreach($aOutput as $sLine)
|
||||
{
|
||||
SetupLog::Ok('Info - mysqldump -V said: '.$sLine);
|
||||
foreach ($aOutput as $sLine) {
|
||||
$aResult[] = new CheckResult(CheckResult::TRACE, 'Info - mysqldump -V said: '.$sLine);
|
||||
}
|
||||
|
||||
|
||||
// create and test destination location
|
||||
//
|
||||
$sDestDir = dirname($sDBBackupPath);
|
||||
setuputils::builddir($sDestDir);
|
||||
if (!is_dir($sDestDir))
|
||||
{
|
||||
if (!is_dir($sDestDir)) {
|
||||
$aResult[] = new CheckResult(CheckResult::ERROR, "$sDestDir does not exist and could not be created.");
|
||||
}
|
||||
|
||||
@@ -590,27 +589,29 @@ class SetupUtils
|
||||
|
||||
/**
|
||||
* Check that graphviz can be launched
|
||||
* @param $sGraphvizPath
|
||||
* @return CheckResult The result of the check
|
||||
* @internal param string $GraphvizPath The path where graphviz' dot program is installed
|
||||
*
|
||||
* @param string $sGraphvizPath The path where graphviz' dot program is installed
|
||||
*
|
||||
* @return CheckResult[] The result of the check AS CheckResult::INFO or CheckResult::WARNING, plus debug traces as some
|
||||
* CheckResult::TRACE
|
||||
*
|
||||
* @since 2.8.0 N°2214 replace SetupLog::Log calls by CheckResult::TRACE
|
||||
*/
|
||||
public static function CheckGraphviz($sGraphvizPath)
|
||||
{
|
||||
$oResult = null;
|
||||
SetupLog::Ok('Info - CheckGraphviz');
|
||||
public static function CheckGraphviz($sGraphvizPath) {
|
||||
$aResult = [];
|
||||
$aResult[] = new CheckResult(CheckResult::TRACE, 'Info - CheckGraphviz');
|
||||
|
||||
// availability of exec()
|
||||
//
|
||||
$aDisabled = explode(', ', ini_get('disable_functions'));
|
||||
SetupLog::Ok('Info - PHP functions disabled: '.implode(', ', $aDisabled));
|
||||
if (in_array('exec', $aDisabled))
|
||||
{
|
||||
$aResult[] = new CheckResult(CheckResult::ERROR, "The PHP exec() function has been disabled on this server");
|
||||
$aResult[] = new CheckResult(CheckResult::TRACE, 'Info - PHP functions disabled: '.implode(', ', $aDisabled));
|
||||
if (in_array('exec', $aDisabled)) {
|
||||
$aResult[] = new CheckResult(CheckResult::ERROR,
|
||||
self::GetStringForJsonEncode('The PHP exec() function has been disabled on this server', 'Could not find Graphviz\' dot'));
|
||||
}
|
||||
|
||||
// availability of dot / dot.exe
|
||||
if (empty($sGraphvizPath))
|
||||
{
|
||||
if (empty($sGraphvizPath)) {
|
||||
$sGraphvizPath = 'dot';
|
||||
}
|
||||
$sCommand = "\"$sGraphvizPath\" -V 2>&1";
|
||||
@@ -618,47 +619,69 @@ class SetupUtils
|
||||
$aOutput = array();
|
||||
$iRetCode = 0;
|
||||
exec($sCommand, $aOutput, $iRetCode);
|
||||
if ($iRetCode == 0)
|
||||
{
|
||||
$oResult = new CheckResult(CheckResult::INFO, "dot is present: ".$aOutput[0]);
|
||||
}
|
||||
elseif ($iRetCode == 1)
|
||||
{
|
||||
$oResult = new CheckResult(CheckResult::WARNING, "dot could not be found: ".implode(' ', $aOutput)." - Please make sure it is installed and in the path.");
|
||||
}
|
||||
else
|
||||
{
|
||||
$oResult = new CheckResult(CheckResult::WARNING, "dot could not be executed (retcode=$iRetCode): Please make sure it is installed and in the path");
|
||||
}
|
||||
foreach($aOutput as $sLine)
|
||||
{
|
||||
SetupLog::Ok('Info - '.$sGraphvizPath.' -V said: '.$sLine);
|
||||
if ($iRetCode == 0) {
|
||||
$aResult[] = new CheckResult(CheckResult::INFO,
|
||||
self::GetStringForJsonEncode("dot is present: ".$aOutput[0], 'Graphviz\' dot found'));
|
||||
} elseif ($iRetCode == 1) {
|
||||
$aResult[] = new CheckResult(CheckResult::WARNING,
|
||||
self::GetStringForJsonEncode(
|
||||
"dot could not be found: ".implode(' ', $aOutput)." - Please make sure it is installed and in the path.",
|
||||
'Could not find Graphviz\' dot'
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$aResult[] = new CheckResult(CheckResult::WARNING,
|
||||
self::GetStringForJsonEncode(
|
||||
"dot could not be executed (retcode=$iRetCode): Please make sure it is installed and in the path",
|
||||
'Could not find Graphviz\' dot'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return $oResult;
|
||||
foreach ($aOutput as $sLine) {
|
||||
$aResult[] = new CheckResult(CheckResult::TRACE, 'Info - '.$sGraphvizPath.' -V said: '.$sLine);
|
||||
}
|
||||
|
||||
return $aResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* This was introduced as on Windows certain messages are not returned correctly :(
|
||||
*
|
||||
* @param string $sValue
|
||||
* @param string $sFallbackValue
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 2.8.0
|
||||
*/
|
||||
private static function GetStringForJsonEncode(string $sValue, string $sFallbackValue): string {
|
||||
return (json_encode($sValue) !== false)
|
||||
? $sValue
|
||||
: $sFallbackValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to retrieve the system's temporary directory
|
||||
* Emulates sys_get_temp_dir if needed (PHP < 5.2.1)
|
||||
*
|
||||
* @return string Path to the system's temp directory
|
||||
*/
|
||||
public static function GetTmpDir()
|
||||
{
|
||||
public static function GetTmpDir() {
|
||||
return realpath(sys_get_temp_dir());
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to retrieve the directory where files are to be uploaded
|
||||
*
|
||||
* @return string Path to the temp directory used for uploading files
|
||||
*/
|
||||
public static function GetUploadTmpDir()
|
||||
{
|
||||
public static function GetUploadTmpDir() {
|
||||
$sPath = ini_get('upload_tmp_dir');
|
||||
if (empty($sPath))
|
||||
{
|
||||
if (empty($sPath)) {
|
||||
$sPath = self::GetTmpDir();
|
||||
}
|
||||
|
||||
return $sPath;
|
||||
}
|
||||
|
||||
@@ -679,30 +702,25 @@ class SetupUtils
|
||||
|
||||
/**
|
||||
* Helper to recursively cleanup a directory
|
||||
*
|
||||
* @param $dir
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function tidydir($dir)
|
||||
{
|
||||
if ((strlen(trim($dir)) == 0) || ($dir == '/') || ($dir == '\\'))
|
||||
{
|
||||
public static function tidydir(string $dir): void {
|
||||
if ((strlen(trim($dir)) == 0) || ($dir == '/') || ($dir == '\\')) {
|
||||
throw new Exception("Attempting to delete directory: '$dir'");
|
||||
}
|
||||
|
||||
$aFiles = scandir($dir); // Warning glob('.*') does not seem to return the broken symbolic links, thus leaving a non-empty directory
|
||||
if ($aFiles !== false)
|
||||
{
|
||||
foreach($aFiles as $file)
|
||||
{
|
||||
if (($file != '.') && ($file != '..'))
|
||||
{
|
||||
if(is_dir($dir.'/'.$file))
|
||||
{
|
||||
if ($aFiles !== false) {
|
||||
foreach ($aFiles as $file) {
|
||||
if (($file != '.') && ($file != '..')) {
|
||||
if (is_dir($dir.'/'.$file)) {
|
||||
self::tidydir($dir.'/'.$file);
|
||||
self::rmdir_safe($dir.'/'.$file);
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
if (!unlink($dir.'/'.$file))
|
||||
{
|
||||
SetupLog::Ok("Warning - FAILED to remove file '$dir/$file'");
|
||||
@@ -2076,28 +2094,28 @@ JS
|
||||
*
|
||||
* @throws \SecurityException
|
||||
*/
|
||||
public final static function CheckSetupToken($bRemoveToken = false)
|
||||
{
|
||||
public final static function CheckSetupToken($bRemoveToken = false) {
|
||||
$sAuthent = utils::ReadParam('authent', '', false, 'raw_data');
|
||||
$sTokenFile = APPROOT.'data/setup/authent';
|
||||
if (!file_exists($sTokenFile) || $sAuthent !== file_get_contents($sTokenFile))
|
||||
{
|
||||
if (!file_exists($sTokenFile) || $sAuthent !== file_get_contents($sTokenFile)) {
|
||||
throw new SecurityException('Setup operations are not allowed outside of the setup');
|
||||
}
|
||||
if ($bRemoveToken)
|
||||
{
|
||||
if ($bRemoveToken) {
|
||||
@unlink($sTokenFile);
|
||||
}
|
||||
}
|
||||
|
||||
private final static function Log($sText)
|
||||
{
|
||||
if (class_exists('SetupPage'))
|
||||
{
|
||||
/**
|
||||
* @param string $sText
|
||||
*
|
||||
* @since 2.7.0 N°2240 Maintenance mode
|
||||
* @since 2.8.0 N°2522 uses SetupLog instead of SetupPage (but still uses SetupPage for setup/console detection)
|
||||
*/
|
||||
private static function Log($sText) {
|
||||
if (class_exists('SetupPage')) {
|
||||
SetupLog::Ok($sText);
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
IssueLog::Info($sText);
|
||||
}
|
||||
}
|
||||
@@ -2105,8 +2123,7 @@ JS
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public static function GetPHPMandatoryExtensions(): array
|
||||
{
|
||||
public static function GetPHPMandatoryExtensions() {
|
||||
return [
|
||||
'mysqli',
|
||||
'iconv',
|
||||
@@ -2128,14 +2145,13 @@ JS
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public static function GetPHPOptionalExtensions(): array
|
||||
{
|
||||
public static function GetPHPOptionalExtensions() {
|
||||
$aOptionalExtensions = [
|
||||
'mcrypt, sodium or openssl' => [
|
||||
'mcrypt' => 'Strong encryption will not be used.',
|
||||
'sodium' => 'Strong encryption will not be used.',
|
||||
'openssl' => 'Strong encryption will not be used.',
|
||||
],
|
||||
'mcrypt' => 'Strong encryption will not be used.',
|
||||
'sodium' => 'Strong encryption will not be used.',
|
||||
'openssl' => 'Strong encryption will not be used.',
|
||||
],
|
||||
'ldap' => 'LDAP authentication will be disabled.',
|
||||
'mbstring' => 'For CryptEngine implementations, trace in Mail to ticket automation', // N°2891
|
||||
];
|
||||
|
||||
@@ -106,17 +106,21 @@ EOF
|
||||
switch($oCheckResult->iSeverity)
|
||||
{
|
||||
case CheckResult::ERROR:
|
||||
$aErrors[] = $oCheckResult->sLabel;
|
||||
$this->bCanMoveForward = false;
|
||||
break;
|
||||
$aErrors[] = $oCheckResult->sLabel;
|
||||
$this->bCanMoveForward = false;
|
||||
break;
|
||||
|
||||
case CheckResult::WARNING:
|
||||
$aWarnings[] = $oCheckResult->sLabel;
|
||||
break;
|
||||
$aWarnings[] = $oCheckResult->sLabel;
|
||||
break;
|
||||
|
||||
case CheckResult::INFO:
|
||||
$aInfo[] = $oCheckResult->sLabel;
|
||||
break;
|
||||
$aInfo[] = $oCheckResult->sLabel;
|
||||
break;
|
||||
|
||||
case CheckResult::TRACE:
|
||||
SetupLog::Ok($oCheckResult->sLabel);
|
||||
break;
|
||||
}
|
||||
}
|
||||
$sStyle = 'style="display:none;max-height:196px;overflow:auto;"';
|
||||
@@ -287,16 +291,18 @@ HTML
|
||||
$aBackupChecks = SetupUtils::CheckBackupPrerequisites($sDBBackupPath, $sMySQLBinDir);
|
||||
$bCanBackup = true;
|
||||
$sMySQLDumpMessage = '';
|
||||
foreach($aBackupChecks as $oCheck)
|
||||
{
|
||||
if ($oCheck->iSeverity == CheckResult::ERROR)
|
||||
{
|
||||
$bCanBackup = false;
|
||||
$sMySQLDumpMessage .= '<div class="message message-error"><span class="message-title">Error:</span>'.$oCheck->sLabel.'</div>';
|
||||
}
|
||||
else
|
||||
{
|
||||
$sMySQLDumpMessage .= '<div class="message message-valid"><span class="message-title">Success:</span>'.$oCheck->sLabel.'</div>';
|
||||
foreach ($aBackupChecks as $oCheck) {
|
||||
switch ($oCheck->iSeverity) {
|
||||
case CheckResult::ERROR:
|
||||
$bCanBackup = false;
|
||||
$sMySQLDumpMessage .= '<div class="message message-error"><span class="message-title">Error:</span>'.$oCheck->sLabel.'</div>';
|
||||
break;
|
||||
case CheckResult::TRACE:
|
||||
SetupLog::Ok($oCheck->sLabel);
|
||||
break;
|
||||
default:
|
||||
$sMySQLDumpMessage .= '<div class="message message-valid"><span class="message-title">Success:</span>'.$oCheck->sLabel.'</div>';
|
||||
break;
|
||||
}
|
||||
}
|
||||
$sChecked = ($bCanBackup && $bDBBackup) ? ' checked ' : '';
|
||||
@@ -1033,38 +1039,48 @@ EOF
|
||||
);
|
||||
}
|
||||
|
||||
public function AsyncAction(WebPage $oPage, $sCode, $aParameters)
|
||||
{
|
||||
switch($sCode)
|
||||
{
|
||||
public function AsyncAction(WebPage $oPage, $sCode, $aParameters) {
|
||||
switch ($sCode) {
|
||||
case 'check_graphviz':
|
||||
$sGraphvizPath = $aParameters['graphviz_path'];
|
||||
$oCheck = SetupUtils::CheckGraphviz($sGraphvizPath);
|
||||
$sMessage = json_encode($oCheck->sLabel);
|
||||
switch($oCheck->iSeverity)
|
||||
{
|
||||
case CheckResult::INFO:
|
||||
$sStatus = 'ok';
|
||||
$sInfoExplanation = (json_encode($oCheck->sLabel) !== false) ? $oCheck->sLabel : 'Graphviz\' dot found';
|
||||
$sMessage = json_encode('<div class="message message-valid">'.$sInfoExplanation.'</div>');
|
||||
$sGraphvizPath = $aParameters['graphviz_path'];
|
||||
$aCheck = SetupUtils::CheckGraphviz($sGraphvizPath);
|
||||
|
||||
break;
|
||||
// N°2214 logging TRACE results
|
||||
$aTraceCheck = CheckResult::FilterCheckResultArray($aCheck, [CheckResult::TRACE]);
|
||||
foreach ($aTraceCheck as $oTraceCheck) {
|
||||
SetupLog::Ok($oTraceCheck->sLabel);
|
||||
}
|
||||
|
||||
default:
|
||||
case CheckResult::ERROR:
|
||||
case CheckResult::WARNING:
|
||||
$sStatus = 'ko';
|
||||
$sErrorExplanation = (json_encode($oCheck->sLabel) !== false) ? $oCheck->sLabel : 'Could not find Graphviz\' dot';
|
||||
$sMessage = json_encode('<div class="message message-error">'.$sErrorExplanation.'</div>');
|
||||
$aNonTraceCheck = array_diff($aCheck, $aTraceCheck);
|
||||
foreach ($aNonTraceCheck as $oCheck) {
|
||||
switch ($oCheck->iSeverity) {
|
||||
case CheckResult::INFO:
|
||||
$sStatus = 'ok';
|
||||
$sInfoExplanation = $oCheck->sLabel;
|
||||
$sMessage = json_encode('<div class="message message-valid">'.$sInfoExplanation.'</div>');
|
||||
|
||||
}
|
||||
$oPage->add_ready_script(
|
||||
<<<EOF
|
||||
break;
|
||||
|
||||
default:
|
||||
case CheckResult::ERROR:
|
||||
case CheckResult::WARNING:
|
||||
$sStatus = 'ko';
|
||||
$sErrorExplanation = $oCheck->sLabel;
|
||||
$sMessage = json_encode('<div class="message message-error">'.$sErrorExplanation.'</div>');
|
||||
break;
|
||||
}
|
||||
|
||||
if ($oCheck->iSeverity !== CheckResult::TRACE) {
|
||||
$oPage->add_ready_script(
|
||||
<<<JS
|
||||
$("#graphviz_status").html($sMessage);
|
||||
$('#btn_next').attr('data-graphviz', '$sStatus');
|
||||
EOF
|
||||
);
|
||||
break;
|
||||
JS
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1167,32 +1183,39 @@ EOF
|
||||
switch($sCode)
|
||||
{
|
||||
case 'check_graphviz':
|
||||
$sGraphvizPath = $aParameters['graphviz_path'];
|
||||
$oCheck = SetupUtils::CheckGraphviz($sGraphvizPath);
|
||||
$sMessage = json_encode($oCheck->sLabel);
|
||||
switch($oCheck->iSeverity)
|
||||
{
|
||||
case CheckResult::INFO:
|
||||
$sStatus = 'ok';
|
||||
$sInfoExplanation = (json_encode($oCheck->sLabel) !== false) ? $oCheck->sLabel : 'Graphviz\' dot found';
|
||||
$sMessage = json_encode('<div class="message message-valid">'.$sInfoExplanation.'</div>');
|
||||
$sGraphvizPath = $aParameters['graphviz_path'];
|
||||
$aCheck = SetupUtils::CheckGraphviz($sGraphvizPath);
|
||||
|
||||
break;
|
||||
// N°2214 logging TRACE results
|
||||
$aTraceCheck = CheckResult::FilterCheckResultArray($aCheck, [CheckResult::TRACE]);
|
||||
foreach ($aTraceCheck as $oTraceCheck) {
|
||||
SetupLog::Ok($oTraceCheck->sLabel);
|
||||
}
|
||||
|
||||
default:
|
||||
case CheckResult::ERROR:
|
||||
case CheckResult::WARNING:
|
||||
$sStatus = 'ko';
|
||||
$sErrorExplanation = (json_encode($oCheck->sLabel) !== false) ? $oCheck->sLabel : 'Could not find Graphviz\' dot';
|
||||
$sMessage = json_encode('<div class="message message-error">'.$sErrorExplanation.'</div>');
|
||||
$aNonTraceCheck = array_diff($aCheck, $aTraceCheck);
|
||||
foreach ($aNonTraceCheck as $oCheck) {
|
||||
switch ($oCheck->iSeverity) {
|
||||
case CheckResult::INFO:
|
||||
$sStatus = 'ok';
|
||||
$sInfoExplanation = $oCheck->sLabel;
|
||||
$sMessage = json_encode('<div class="message message-valid">'.$sInfoExplanation.'</div>');
|
||||
break;
|
||||
|
||||
}
|
||||
$oPage->add_ready_script(
|
||||
<<<EOF
|
||||
default:
|
||||
case CheckResult::ERROR:
|
||||
case CheckResult::WARNING:
|
||||
$sStatus = 'ko';
|
||||
$sErrorExplanation = $oCheck->sLabel;
|
||||
$sMessage = json_encode('<div class="message message-error">'.$sErrorExplanation.'</div>');
|
||||
break;
|
||||
}
|
||||
$oPage->add_ready_script(
|
||||
<<<JS
|
||||
$("#graphviz_status").html($sMessage);
|
||||
$('#btn_next').attr('data-graphviz', '$sStatus');
|
||||
EOF
|
||||
);
|
||||
JS
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ function UsageAndExit($oP)
|
||||
if ($bModeCLI)
|
||||
{
|
||||
$oP->p("USAGE:\n");
|
||||
$oP->p("php -q synchro_exec.php --auth_user=<login> --auth_pwd=<password> --data_sources=<comma_separated_list_of_data_sources> [max_chunk_size=<limit the count of replica loaded in a single pass>]\n");
|
||||
$oP->p("php -q synchro_exec.php --auth_user=<login> --auth_pwd=<password> --data_sources=<comma_separated_list_of_data_sources> [--max_chunk_size=<limit the count of replica loaded in a single pass>] [--simulate=<If set to 1, then the synchro will not be executed, but the expected report will be produced>]\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -89,12 +89,8 @@ catch(Exception $e)
|
||||
|
||||
if (utils::IsModeCLI())
|
||||
{
|
||||
// Next steps:
|
||||
// specific arguments: 'csvfile'
|
||||
//
|
||||
$sAuthUser = ReadMandatoryParam($oP, 'auth_user', 'raw_data');
|
||||
$sAuthPwd = ReadMandatoryParam($oP, 'auth_pwd', 'raw_data');
|
||||
$sDataSourcesList = ReadMandatoryParam($oP, 'data_sources', 'raw_data'); // May contain commas
|
||||
if (UserRights::CheckCredentials($sAuthUser, $sAuthPwd))
|
||||
{
|
||||
UserRights::Login($sAuthUser); // Login & set the user's language
|
||||
@@ -110,16 +106,15 @@ else
|
||||
{
|
||||
require_once(APPROOT.'/application/loginwebpage.class.inc.php');
|
||||
LoginWebPage::DoLogin(); // Check user rights and prompt if needed
|
||||
|
||||
$sDataSourcesList = utils::ReadParam('data_sources', null, true, 'raw_data');
|
||||
|
||||
if ($sDataSourcesList == null)
|
||||
{
|
||||
UsageAndExit($oP);
|
||||
}
|
||||
}
|
||||
|
||||
$bSimulate = (utils::ReadParam('simulate', '0', true) == '1');
|
||||
$sDataSourcesList = ReadMandatoryParam($oP, 'data_sources', 'raw_data'); // May contain commas
|
||||
|
||||
if ($sDataSourcesList == null)
|
||||
{
|
||||
UsageAndExit($oP);
|
||||
}
|
||||
|
||||
|
||||
foreach(explode(',', $sDataSourcesList) as $iSDS)
|
||||
|
||||
@@ -156,27 +156,16 @@ $aPageParams = array
|
||||
function UsageAndExit($oP)
|
||||
{
|
||||
global $aPageParams;
|
||||
$bModeCLI = utils::IsModeCLI();
|
||||
$sMode = utils::IsModeCLI() ? 'cli' : 'http';
|
||||
|
||||
$oP->p("USAGE:\n");
|
||||
foreach ($aPageParams as $sParam => $aParamData)
|
||||
{
|
||||
$aModes = explode(',', $aParamData['modes']);
|
||||
if ($bModeCLI)
|
||||
if (in_array($sMode, $aModes, false))
|
||||
{
|
||||
if (in_array('cli', $aModes, false))
|
||||
{
|
||||
$sDesc = $aParamData['description'].', '.($aParamData['mandatory'] ? 'mandatory' : 'optional, defaults to ['.$aParamData['default'].']');
|
||||
$oP->p("$sParam = $sDesc");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (in_array('http', $aModes, false))
|
||||
{
|
||||
$sDesc = $aParamData['description'].', '.($aParamData['mandatory'] ? 'mandatory' : 'optional, defaults to ['.$aParamData['default'].']');
|
||||
$oP->p("$sParam = $sDesc");
|
||||
}
|
||||
$sDesc = $aParamData['description'].', '.($aParamData['mandatory'] ? 'mandatory' : 'optional, defaults to ['.$aParamData['default'].']');
|
||||
$oP->p("$sParam = $sDesc");
|
||||
}
|
||||
}
|
||||
$oP->output();
|
||||
@@ -523,11 +512,7 @@ try
|
||||
$aValues = array(); // Used to build the insert query
|
||||
foreach ($aRow as $iCol => $value)
|
||||
{
|
||||
if ($value === null) // Source CSV: "<NULL>"
|
||||
{
|
||||
$aValues[] = null;
|
||||
}
|
||||
elseif ($aIsDateToTransform[$iCol] !== false)
|
||||
if ($aIsDateToTransform[$iCol] !== false)
|
||||
{
|
||||
$bDateOnly = false;
|
||||
$sFormat = $sDateTimeFormat;
|
||||
@@ -539,7 +524,7 @@ try
|
||||
$sDate = ChangeDateFormat($value, $sFormat, $bDateOnly);
|
||||
if ($sDate === false)
|
||||
{
|
||||
$aValues[] = CMDBSource::Quote('');
|
||||
$aValues[] = '';
|
||||
if ($sOutput === 'details')
|
||||
{
|
||||
$oP->add("$iRow: Wrong format for {$aIsDateToTransform[$iCol]} column $iCol: '$value' does not match the expected format: '$sFormat' (column skipped)\n");
|
||||
@@ -547,15 +532,15 @@ try
|
||||
}
|
||||
else
|
||||
{
|
||||
$aValues[] = CMDBSource::Quote($sDate);
|
||||
$aValues[] = $sDate;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$aValues[] = CMDBSource::Quote($value);
|
||||
$aValues[] = $value;
|
||||
}
|
||||
}
|
||||
$sValues = implode(', ', $aValues);
|
||||
$sValues = implode(', ', CMDBSource::Quote($aValues));
|
||||
$sInsert = "INSERT INTO `$sTable` ($sInsertColumns) VALUES ($sValues)";
|
||||
try
|
||||
{
|
||||
|
||||
568
test/synchro/DataSynchroTest.php
Normal file
568
test/synchro/DataSynchroTest.php
Normal file
@@ -0,0 +1,568 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2013-2020 Combodo SARL
|
||||
* This file is part of iTop.
|
||||
* iTop is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
* iTop is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\Test\UnitTest\Synchro;
|
||||
|
||||
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
|
||||
use DBObjectSet;
|
||||
use DBSearch;
|
||||
use DBObjectSearch;
|
||||
use Exception;
|
||||
use MetaModel;
|
||||
use SynchroDataSource;
|
||||
use utils;
|
||||
use UserLocal;
|
||||
|
||||
|
||||
class DataSynchroTest extends ItopDataTestCase
|
||||
{
|
||||
protected const AUTH_USER = 'DataSynchroTest';
|
||||
protected const AUTH_PWD = 'sdf234(-fgh;,dfgDFG';
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
// Create the login account if it does not exist yet
|
||||
$oSearch = DBSearch::FromOQL('SELECT User WHERE login = "'.static::AUTH_USER.'"');
|
||||
$oSet = new DBObjectSet($oSearch);
|
||||
if ($oSet->Count() == 0)
|
||||
{
|
||||
$oProfileSearch = DBSearch::FromOQL('SELECT URP_Profiles WHERE name LIKE "administrator"');
|
||||
$oProfileSet = new DBObjectSet($oProfileSearch);
|
||||
$oAdminProfile = $oProfileSet->fetch();
|
||||
|
||||
$oUser = MetaModel::NewObject('UserLocal', array(
|
||||
'login' => static::AUTH_USER,
|
||||
'password' => static::AUTH_PWD,
|
||||
'expiration' => UserLocal::EXPIRE_NEVER,
|
||||
));
|
||||
$oProfiles = $oUser->Get('profile_list');
|
||||
$oProfiles->AddItem(MetaModel::NewObject('URP_UserProfile', array(
|
||||
'profileid' => $oAdminProfile->GetKey()
|
||||
)));
|
||||
$oUser->Set('profile_list', $oProfiles);
|
||||
$oUser->DBInsertNoReload();
|
||||
}
|
||||
}
|
||||
|
||||
protected function ExecSynchroImport($aParams)
|
||||
{
|
||||
$aParams['auth_user'] = static::AUTH_USER;
|
||||
$aParams['auth_pwd'] = static::AUTH_PWD;
|
||||
return utils::ExecITopScript('synchro/synchro_import.php', $aParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run a series of data synchronization through the REST API
|
||||
*
|
||||
* @dataProvider SynchroScenariosProvider
|
||||
*
|
||||
* @param $sDescription
|
||||
* @param $sTargetClass
|
||||
* @param $aSourceProperties
|
||||
* @param $aSourceData
|
||||
* @param $aTargetData
|
||||
* @param $aAttributes
|
||||
*
|
||||
* @throws \ArchivedObjectException
|
||||
* @throws \CoreCannotSaveObjectException
|
||||
* @throws \CoreException
|
||||
* @throws \CoreUnexpectedValue
|
||||
* @throws \CoreWarning
|
||||
* @throws \DictExceptionMissingString
|
||||
* @throws \MySQLException
|
||||
* @throws \OQLException
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function testSynchroImportPage($sDescription, $sTargetClass, $aSourceProperties, $aSourceData, $aTargetData, $aAttributes)
|
||||
{
|
||||
$sClass = $sTargetClass;
|
||||
|
||||
$aTargetAttributes = array_shift($aTargetData);
|
||||
$aSourceAttributes = array_shift($aSourceData);
|
||||
|
||||
if (count($aSourceData) + 1 != count($aTargetData))
|
||||
{
|
||||
throw new Exception("Target data must contain exactly ".(count($aSourceData) + 1)." items, found ".count($aTargetData));
|
||||
}
|
||||
|
||||
// Create the data source
|
||||
//
|
||||
$oDataSource = new SynchroDataSource();
|
||||
$oDataSource->Set('name', 'Test data sync '.time());
|
||||
$oDataSource->Set('description', 'unit test - created automatically');
|
||||
$oDataSource->Set('status', 'production');
|
||||
$oDataSource->Set('user_id', 0);
|
||||
$oDataSource->Set('scope_class', $sClass);
|
||||
foreach ($aSourceProperties as $sProperty => $value)
|
||||
{
|
||||
$oDataSource->Set($sProperty, $value);
|
||||
}
|
||||
$iDataSourceId = $oDataSource->DBInsert();
|
||||
|
||||
$oAttributeSet = $oDataSource->Get('attribute_list');
|
||||
while ($oAttribute = $oAttributeSet->Fetch())
|
||||
{
|
||||
if (array_key_exists($oAttribute->Get('attcode'), $aAttributes))
|
||||
{
|
||||
$aAttribInfo = $aAttributes[$oAttribute->Get('attcode')];
|
||||
if (array_key_exists('reconciliation_attcode', $aAttribInfo))
|
||||
{
|
||||
$oAttribute->Set('reconciliation_attcode', $aAttribInfo['reconciliation_attcode']);
|
||||
}
|
||||
$oAttribute->Set('update', $aAttribInfo['do_update']);
|
||||
$oAttribute->Set('reconcile', $aAttribInfo['do_reconcile']);
|
||||
}
|
||||
else
|
||||
{
|
||||
$oAttribute->Set('update', false);
|
||||
$oAttribute->Set('reconcile', false);
|
||||
}
|
||||
$oAttribute->DBUpdate();
|
||||
}
|
||||
|
||||
// Prepare list of prefixes -> make sure objects are unique with regard to the reconciliation scheme
|
||||
$aPrefixes = array(); // attcode => prefix
|
||||
foreach($aSourceAttributes as $iDummy => $sAttCode)
|
||||
{
|
||||
$aPrefixes[$sAttCode] = ''; // init with something
|
||||
}
|
||||
foreach($aAttributes as $sAttCode => $aAttribInfo)
|
||||
{
|
||||
if (isset($aAttribInfo['automatic_prefix']) && $aAttribInfo['automatic_prefix'])
|
||||
{
|
||||
$aPrefixes[$sAttCode] = 'TEST_'.$iDataSourceId.'_';
|
||||
}
|
||||
}
|
||||
|
||||
// List existing objects (to be ignored in the analysis
|
||||
//
|
||||
$oAllObjects = new DBObjectSet(new DBObjectSearch($sClass));
|
||||
$aExisting = $oAllObjects->ToArray(true);
|
||||
$sExistingIds = implode(', ', array_keys($aExisting));
|
||||
|
||||
// Create the initial object list
|
||||
//
|
||||
$aInitialTarget = $aTargetData[0];
|
||||
foreach($aInitialTarget as $aObjFields)
|
||||
{
|
||||
$oNewTarget = MetaModel::NewObject($sClass);
|
||||
foreach($aTargetAttributes as $iAtt => $sAttCode)
|
||||
{
|
||||
$oNewTarget->Set($sAttCode, $aPrefixes[$sAttCode].$aObjFields[$iAtt]);
|
||||
}
|
||||
$oNewTarget->DBInsertNoReload();
|
||||
}
|
||||
|
||||
foreach($aTargetData as $iRow => $aExpectedObjects)
|
||||
{
|
||||
// Check the status (while ignoring existing objects)
|
||||
//
|
||||
if (empty($sExistingIds))
|
||||
{
|
||||
$oObjects = new DBObjectSet(DBObjectSearch::FromOQL("SELECT $sClass"));
|
||||
}
|
||||
else
|
||||
{
|
||||
$oObjects = new DBObjectSet(DBObjectSearch::FromOQL("SELECT $sClass WHERE id NOT IN($sExistingIds)"));
|
||||
}
|
||||
$aFound = $oObjects->ToArray();
|
||||
$aErrors_Unexpected = array();
|
||||
foreach($aFound as $iObj => $oObj)
|
||||
{
|
||||
// Is this object in the expected objects list
|
||||
$bFoundMatch = false;
|
||||
foreach($aExpectedObjects as $iExp => $aValues)
|
||||
{
|
||||
$bDoesMatch = true;
|
||||
foreach($aTargetAttributes as $iCol => $sAttCode)
|
||||
{
|
||||
if ($oObj->Get($sAttCode) != $aPrefixes[$sAttCode].$aValues[$iCol])
|
||||
{
|
||||
$bDoesMatch = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($bDoesMatch)
|
||||
{
|
||||
$bFoundMatch = true;
|
||||
unset($aExpectedObjects[$iExp]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$bFoundMatch)
|
||||
{
|
||||
$aObjDesc = array();
|
||||
foreach($aTargetAttributes as $iCol => $sAttCode)
|
||||
{
|
||||
$aObjDesc[$sAttCode] = $oObj->Get($sAttCode);
|
||||
}
|
||||
$aErrors_Unexpected[get_class($oObj).'::'.$oObj->GetKey()] = $aObjDesc;
|
||||
}
|
||||
}
|
||||
|
||||
// Display the current status
|
||||
//
|
||||
$aErrors = array();
|
||||
if (count($aErrors_Unexpected) > 0) {
|
||||
$aErrors[] = "Unexpected objects found in iTop DB after step $iRow (starting at 0):\n".print_r($aErrors_Unexpected, true);
|
||||
}
|
||||
if (count($aExpectedObjects) > 0) {
|
||||
$aErrors[] = "Expected objects NOT found in iTop DB after step $iRow (starting at 0)\n".print_r($aExpectedObjects, true);
|
||||
}
|
||||
if (count($aErrors) > 0) {
|
||||
static::fail(implode("\n", $aErrors));
|
||||
}
|
||||
else {
|
||||
static::assertTrue(true);
|
||||
}
|
||||
|
||||
// If not on the final row, run a data exchange sequence
|
||||
//
|
||||
if (array_key_exists($iRow, $aSourceData))
|
||||
{
|
||||
$aToBeLoaded = $aSourceData[$iRow];
|
||||
|
||||
// First line
|
||||
$sCsvData = implode(';', $aSourceAttributes)."\n";
|
||||
|
||||
$sTextQualifier = '"';
|
||||
|
||||
foreach($aToBeLoaded as $aDataRow)
|
||||
{
|
||||
$aFinalData = array();
|
||||
foreach($aDataRow as $iCol => $value)
|
||||
{
|
||||
$sAttCode = $aSourceAttributes[$iCol];
|
||||
$sRawValue = $aPrefixes[$sAttCode].$value;
|
||||
|
||||
$sFrom = array("\r\n", $sTextQualifier);
|
||||
$sTo = array("\n", $sTextQualifier.$sTextQualifier);
|
||||
$sCSVValue = $sTextQualifier.str_replace($sFrom, $sTo, (string)$sRawValue).$sTextQualifier;
|
||||
|
||||
$aFinalData[] = $sCSVValue;
|
||||
}
|
||||
$sCsvData .= implode(';', $aFinalData)."\n";
|
||||
}
|
||||
$sCSVTmpFile = tempnam(sys_get_temp_dir(), "CSV");
|
||||
file_put_contents($sCSVTmpFile, $sCsvData);
|
||||
|
||||
$aParams = array(
|
||||
'csvfile' => $sCSVTmpFile,
|
||||
'data_source_id' => $iDataSourceId,
|
||||
'separator' => ';',
|
||||
'simulate' => 0,
|
||||
'output' => 'details',
|
||||
);
|
||||
list($iRetCode, $aOutputLines) = static::ExecSynchroImport($aParams);
|
||||
|
||||
unlink($sCSVTmpFile);
|
||||
|
||||
// Report the load results
|
||||
//
|
||||
if (strlen($sCsvData) > 5000)
|
||||
{
|
||||
$sCsvDataViewable = 'INPUT TOO LONG TO BE DISPLAYED ('.strlen($sCsvData).")\n".substr($sCsvData, 0, 500)."\n... TO BE CONTINUED";
|
||||
}
|
||||
else
|
||||
{
|
||||
$sCsvDataViewable = $sCsvData;
|
||||
}
|
||||
echo "Input Data:\n";
|
||||
echo $sCsvDataViewable;
|
||||
echo "\n";
|
||||
|
||||
$sResultsViewable = '| '.implode("\n| ", $aOutputLines);
|
||||
|
||||
echo "Results:\n";
|
||||
echo $sResultsViewable;
|
||||
echo "\n";
|
||||
|
||||
if ($iRetCode != 0)
|
||||
{
|
||||
static::fail("Execution of synchro_import failing with code '$iRetCode', see error.log for more details");
|
||||
}
|
||||
|
||||
if (stripos($sResultsViewable, 'exception') !== false)
|
||||
{
|
||||
self::fail('Encountered an Exception during the last import/synchro');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function SynchroScenariosProvider()
|
||||
{
|
||||
$aTestCases = array();
|
||||
$aTestCases['Load user logins'] = array(
|
||||
'desc' => 'Load user logins',
|
||||
'target_class' => 'UserLocal',
|
||||
'source_properties' => array(
|
||||
'full_load_periodicity' => 3600, // should be ignored in this case
|
||||
'reconciliation_policy' => 'use_attributes',
|
||||
'action_on_zero' => 'create',
|
||||
'action_on_one' => 'update',
|
||||
'action_on_multiple' => 'error',
|
||||
'delete_policy' => 'delete',
|
||||
'delete_policy_update' => '',
|
||||
'delete_policy_retention' => 0,
|
||||
),
|
||||
'source_data' => array(
|
||||
array('primary_key', 'login', 'password', 'profile_list'),
|
||||
array(
|
||||
array('user_A', 'login_A', 'password_A', 'profileid:10;reason:he/she is managing services'),
|
||||
),
|
||||
),
|
||||
'target_data' => array(
|
||||
array('login'),
|
||||
array(
|
||||
// Initial state
|
||||
),
|
||||
array(
|
||||
array('login_A'),
|
||||
),
|
||||
),
|
||||
'attributes' => array(
|
||||
'login' => array(
|
||||
'do_reconcile' => true,
|
||||
'do_update' => true,
|
||||
'automatic_prefix' => true, // unique id (for unit testing)
|
||||
),
|
||||
'password' => array(
|
||||
'do_reconcile' => false,
|
||||
'do_update' => true,
|
||||
),
|
||||
'profile_list' => array(
|
||||
'do_reconcile' => false,
|
||||
'do_update' => true,
|
||||
),
|
||||
)
|
||||
);
|
||||
$aTestCases['Simple scenario with delete option (and extkey given as org/name)'] = array(
|
||||
'desc' => 'Simple scenario with delete option (and extkey given as org/name)',
|
||||
'target_class' => 'ApplicationSolution',
|
||||
'source_properties' => array(
|
||||
'full_load_periodicity' => 1,
|
||||
'reconciliation_policy' => 'use_attributes',
|
||||
'action_on_zero' => 'create',
|
||||
'action_on_one' => 'update',
|
||||
'action_on_multiple' => 'error',
|
||||
'delete_policy' => 'delete',
|
||||
'delete_policy_update' => '',
|
||||
'delete_policy_retention' => 0,
|
||||
),
|
||||
'source_data' => array(
|
||||
array('primary_key', 'org_id', 'name', 'status'),
|
||||
array(
|
||||
array('obj_A', '<NULL>', 'obj_A', 'active'), // org_id unchanged
|
||||
array('obj_B', '_DUMMY_', 'obj_B', 'active'), // error, '_DUMMY_' unknown
|
||||
array('obj_C', 'SOMECODE', 'obj_C', 'active'),
|
||||
array('obj_D', 'SOMECODE', 'obj_D', 'active'),
|
||||
array('obj_E', 'SOMECODE', 'obj_E', 'active'),
|
||||
),
|
||||
array(
|
||||
array('obj_D', 'SOMECODE', 'obj_D', 'inactive'),
|
||||
array('obj_E', 'SOMECODE', 'obj_E', '<NULL>'),
|
||||
),
|
||||
),
|
||||
'target_data' => array(
|
||||
array('org_id', 'name', 'status'),
|
||||
array(
|
||||
// Initial state
|
||||
array(2, 'obj_A', 'active'),
|
||||
array(2, 'obj_B', 'active'),
|
||||
),
|
||||
array(
|
||||
array(2, 'obj_A', 'active'),
|
||||
array(2, 'obj_B', 'active'),
|
||||
array(1, 'obj_C', 'active'),
|
||||
array(1, 'obj_D', 'active'),
|
||||
array(1, 'obj_E', 'active'),
|
||||
),
|
||||
array(
|
||||
array(2, 'obj_A', 'active'),
|
||||
array(2, 'obj_B', 'active'),
|
||||
array(1, 'obj_D', 'inactive'),
|
||||
array(1, 'obj_E', 'active'),
|
||||
),
|
||||
),
|
||||
'attributes' => array(
|
||||
'org_id' => array(
|
||||
'do_reconcile' => false,
|
||||
'do_update' => true,
|
||||
'reconciliation_attcode' => 'code',
|
||||
),
|
||||
'name' => array(
|
||||
'do_reconcile' => true,
|
||||
'do_update' => true,
|
||||
'automatic_prefix' => true, // unique id
|
||||
),
|
||||
'status' => array(
|
||||
'do_reconcile' => false,
|
||||
'do_update' => true,
|
||||
),
|
||||
),
|
||||
);
|
||||
$aTestCases['Update then delete with retention (to complete with manual testing) and reconciliation on org/name'] = array(
|
||||
'desc' => 'Update then delete with retention (to complete with manual testing) and reconciliation on org/name',
|
||||
'target_class' => 'ApplicationSolution',
|
||||
'source_properties' => array(
|
||||
'full_load_periodicity' => 0,
|
||||
'reconciliation_policy' => 'use_attributes',
|
||||
'action_on_zero' => 'create',
|
||||
'action_on_one' => 'update',
|
||||
'action_on_multiple' => 'error',
|
||||
'delete_policy' => 'update_then_delete',
|
||||
'delete_policy_update' => 'status:inactive',
|
||||
'delete_policy_retention' => 15,
|
||||
),
|
||||
'source_data' => array(
|
||||
array('primary_key', 'org_id', 'name', 'status'),
|
||||
array(
|
||||
array('obj_A', 'Demo', 'obj_A', 'active'),
|
||||
),
|
||||
array(
|
||||
),
|
||||
),
|
||||
'target_data' => array(
|
||||
array('org_id', 'name', 'status'),
|
||||
array(
|
||||
// Initial state
|
||||
),
|
||||
array(
|
||||
array(3, 'obj_A', 'active'),
|
||||
),
|
||||
array(
|
||||
array(3, 'obj_A', 'inactive'),
|
||||
// deleted !
|
||||
),
|
||||
),
|
||||
'attributes' => array(
|
||||
'org_id' => array(
|
||||
'do_reconcile' => true,
|
||||
'do_update' => true,
|
||||
'reconciliation_attcode' => 'name',
|
||||
),
|
||||
'name' => array(
|
||||
'do_reconcile' => true,
|
||||
'do_update' => true,
|
||||
'automatic_prefix' => true, // unique id
|
||||
),
|
||||
'status' => array(
|
||||
'do_reconcile' => false,
|
||||
'do_update' => true,
|
||||
),
|
||||
),
|
||||
);
|
||||
$aTestCases['Simple scenario loading a few ApplicationSolution'] = array(
|
||||
'desc' => 'Simple scenario loading a few ApplicationSolution',
|
||||
'target_class' => 'ApplicationSolution',
|
||||
'source_properties' => array(
|
||||
'full_load_periodicity' => 0,
|
||||
'reconciliation_policy' => 'use_attributes',
|
||||
'action_on_zero' => 'create',
|
||||
'action_on_one' => 'update',
|
||||
'action_on_multiple' => 'error',
|
||||
'delete_policy' => 'update',
|
||||
'delete_policy_update' => 'status:inactive',
|
||||
'delete_policy_retention' => 0,
|
||||
|
||||
),
|
||||
'source_data' => array(
|
||||
array('primary_key', 'org_id', 'name', 'status'),
|
||||
array(
|
||||
array('obj_A', 2, 'obj_A', 'active'),
|
||||
array('obj_B', 2, 'obj_B', 'inactive'),
|
||||
array('obj_C', 2, 'obj_C', 'inactive'),
|
||||
),
|
||||
array(
|
||||
array('obj_A', 2, 'obj_A', 'active'),
|
||||
array('obj_B', 2, 'obj_B', 'inactive'),
|
||||
array('obj_C', 2, 'obj_C', 'inactive'),
|
||||
),
|
||||
array(
|
||||
array('obj_A', 2, 'obj_A', 'active'),
|
||||
array('obj_C', 2, 'obj_C', 'inactive'),
|
||||
array('obj_D', 2, 'obj_D', 'inactive'),
|
||||
),
|
||||
array(
|
||||
array('obj_C', 2, 'obj_C', 'active'),
|
||||
),
|
||||
array(
|
||||
array('obj_C', 2, 'obj_C', 'active'),
|
||||
),
|
||||
),
|
||||
'target_data' => array(
|
||||
array('org_id', 'name', 'status'),
|
||||
array(
|
||||
// Initial state
|
||||
array(2, 'obj_A', 'inactive'),
|
||||
array(2, 'obj_B', 'active'),
|
||||
array(2, 'obj_B', 'inactive'),
|
||||
),
|
||||
array(
|
||||
array(2, 'obj_A', 'active'),
|
||||
array(2, 'obj_B', 'active'),
|
||||
array(2, 'obj_B', 'inactive'),
|
||||
array(2, 'obj_C', 'inactive'),
|
||||
),
|
||||
array(
|
||||
array(2, 'obj_A', 'active'),
|
||||
array(2, 'obj_B', 'active'),
|
||||
array(2, 'obj_B', 'inactive'),
|
||||
array(2, 'obj_C', 'inactive'),
|
||||
),
|
||||
array(
|
||||
array(2, 'obj_A', 'active'),
|
||||
array(2, 'obj_B', 'active'),
|
||||
array(2, 'obj_B', 'inactive'),
|
||||
array(2, 'obj_C', 'inactive'),
|
||||
array(2, 'obj_D', 'inactive'),
|
||||
),
|
||||
array(
|
||||
array(2, 'obj_A', 'inactive'),
|
||||
array(2, 'obj_B', 'active'),
|
||||
array(2, 'obj_B', 'inactive'),
|
||||
array(2, 'obj_C', 'active'),
|
||||
array(2, 'obj_D', 'inactive'),
|
||||
),
|
||||
array(
|
||||
array(2, 'obj_A', 'inactive'),
|
||||
array(2, 'obj_B', 'active'),
|
||||
array(2, 'obj_B', 'inactive'),
|
||||
array(2, 'obj_C', 'active'),
|
||||
array(2, 'obj_D', 'inactive'),
|
||||
),
|
||||
),
|
||||
'attributes' => array(
|
||||
'org_id' => array(
|
||||
'do_reconcile' => false,
|
||||
'do_update' => true,
|
||||
),
|
||||
'name' => array(
|
||||
'do_reconcile' => true,
|
||||
'do_update' => true,
|
||||
'automatic_prefix' => true, // unique id
|
||||
),
|
||||
'status' => array(
|
||||
'do_reconcile' => false,
|
||||
'do_update' => true,
|
||||
),
|
||||
),
|
||||
);
|
||||
return $aTestCases;
|
||||
}
|
||||
}
|
||||
@@ -1414,546 +1414,6 @@ class TestImportRESTMassive extends TestImportREST
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Test data exchange
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class TestDataExchange extends TestBizModel
|
||||
{
|
||||
static public function GetName()
|
||||
{
|
||||
return 'Data exchange';
|
||||
}
|
||||
|
||||
static public function GetDescription()
|
||||
{
|
||||
return 'Test REST services: synchro_import and synchro_exec';
|
||||
}
|
||||
|
||||
protected function DoExecScenario($aSingleScenario)
|
||||
{
|
||||
echo "<div style=\"padding: 10;\">\n";
|
||||
echo "<h3 style=\"background-color: #ddddff; padding: 10;\">{$aSingleScenario['desc']}</h3>\n";
|
||||
|
||||
$sClass = $aSingleScenario['target_class'];
|
||||
|
||||
$aTargetData = $aSingleScenario['target_data'];
|
||||
$aSourceData = $aSingleScenario['source_data'];
|
||||
|
||||
$aTargetAttributes = array_shift($aTargetData);
|
||||
$aSourceAttributes = array_shift($aSourceData);
|
||||
|
||||
if (count($aSourceData) + 1 != count($aTargetData))
|
||||
{
|
||||
throw new Exception("Target data must contain exactly ".(count($aSourceData) + 1)." items, found ".count($aTargetData));
|
||||
}
|
||||
|
||||
// Create the data source
|
||||
//
|
||||
$oDataSource = new SynchroDataSource();
|
||||
$oDataSource->Set('name', 'Test data sync '.time());
|
||||
$oDataSource->Set('description', 'unit test - created automatically');
|
||||
$oDataSource->Set('status', 'production');
|
||||
$oDataSource->Set('user_id', 0);
|
||||
$oDataSource->Set('scope_class', $sClass);
|
||||
$oDataSource->Set('scope_restriction', '');
|
||||
$oDataSource->Set('full_load_periodicity', $aSingleScenario['full_load_periodicity']);
|
||||
$oDataSource->Set('reconciliation_policy', $aSingleScenario['reconciliation_policy']);
|
||||
$oDataSource->Set('action_on_zero', $aSingleScenario['action_on_zero']);
|
||||
$oDataSource->Set('action_on_one', $aSingleScenario['action_on_one']);
|
||||
$oDataSource->Set('action_on_multiple', $aSingleScenario['action_on_multiple']);
|
||||
$oDataSource->Set('delete_policy', $aSingleScenario['delete_policy']);
|
||||
$oDataSource->Set('delete_policy_update', $aSingleScenario['delete_policy_update']);
|
||||
$oDataSource->Set('delete_policy_retention', $aSingleScenario['delete_policy_retention']);
|
||||
$iDataSourceId = $this->ObjectToDB($oDataSource, true /* reload */);
|
||||
|
||||
$oAttributeSet = $oDataSource->Get('attribute_list');
|
||||
while ($oAttribute = $oAttributeSet->Fetch())
|
||||
{
|
||||
if (array_key_exists($oAttribute->Get('attcode'), $aSingleScenario['attributes']))
|
||||
{
|
||||
$aAttribInfo = $aSingleScenario['attributes'][$oAttribute->Get('attcode')];
|
||||
if (array_key_exists('reconciliation_attcode', $aAttribInfo))
|
||||
{
|
||||
$oAttribute->Set('reconciliation_attcode', $aAttribInfo['reconciliation_attcode']);
|
||||
}
|
||||
$oAttribute->Set('update', $aAttribInfo['do_update']);
|
||||
$oAttribute->Set('reconcile', $aAttribInfo['do_reconcile']);
|
||||
}
|
||||
else
|
||||
{
|
||||
$oAttribute->Set('update', false);
|
||||
$oAttribute->Set('reconcile', false);
|
||||
}
|
||||
$this->UpdateObjectInDB($oAttribute);
|
||||
}
|
||||
|
||||
// Prepare list of prefixes -> make sure objects are unique with regard to the reconciliation scheme
|
||||
$aPrefixes = array(); // attcode => prefix
|
||||
foreach($aSourceAttributes as $iDummy => $sAttCode)
|
||||
{
|
||||
$aPrefixes[$sAttCode] = ''; // init with something
|
||||
}
|
||||
foreach($aSingleScenario['attributes'] as $sAttCode => $aAttribInfo)
|
||||
{
|
||||
if (isset($aAttribInfo['automatic_prefix']) && $aAttribInfo['automatic_prefix'])
|
||||
{
|
||||
$aPrefixes[$sAttCode] = 'TEST_'.$iDataSourceId.'_';
|
||||
}
|
||||
}
|
||||
|
||||
// List existing objects (to be ignored in the analysis
|
||||
//
|
||||
$oAllObjects = new DBObjectSet(new DBObjectSearch($sClass));
|
||||
$aExisting = $oAllObjects->ToArray(true);
|
||||
$sExistingIds = implode(', ', array_keys($aExisting));
|
||||
|
||||
// Create the initial object list
|
||||
//
|
||||
$aInitialTarget = $aTargetData[0];
|
||||
foreach($aInitialTarget as $aObjFields)
|
||||
{
|
||||
$oNewTarget = MetaModel::NewObject($sClass);
|
||||
foreach($aTargetAttributes as $iAtt => $sAttCode)
|
||||
{
|
||||
$oNewTarget->Set($sAttCode, $aPrefixes[$sAttCode].$aObjFields[$iAtt]);
|
||||
}
|
||||
$this->ObjectToDB($oNewTarget);
|
||||
}
|
||||
|
||||
foreach($aTargetData as $iRow => $aExpectedObjects)
|
||||
{
|
||||
sleep(2);
|
||||
// Check the status (while ignoring existing objects)
|
||||
//
|
||||
if (empty($sExistingIds))
|
||||
{
|
||||
$oObjects = new DBObjectSet(DBObjectSearch::FromOQL("SELECT $sClass"));
|
||||
}
|
||||
else
|
||||
{
|
||||
$oObjects = new DBObjectSet(DBObjectSearch::FromOQL("SELECT $sClass WHERE id NOT IN($sExistingIds)"));
|
||||
}
|
||||
$aFound = $oObjects->ToArray();
|
||||
$aErrors_Unexpected = array();
|
||||
foreach($aFound as $iObj => $oObj)
|
||||
{
|
||||
// Is this object in the expected objects list
|
||||
$bFoundMatch = false;
|
||||
foreach($aExpectedObjects as $iExp => $aValues)
|
||||
{
|
||||
$bDoesMatch = true;
|
||||
foreach($aTargetAttributes as $iCol => $sAttCode)
|
||||
{
|
||||
if ($oObj->Get($sAttCode) != $aPrefixes[$sAttCode].$aValues[$iCol])
|
||||
{
|
||||
$bDoesMatch = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($bDoesMatch)
|
||||
{
|
||||
$bFoundMatch = true;
|
||||
unset($aExpectedObjects[$iExp]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$bFoundMatch)
|
||||
{
|
||||
$aErrors_Unexpected[] = $oObj->GetKey();
|
||||
}
|
||||
}
|
||||
|
||||
// Display the current status
|
||||
//
|
||||
echo "<p>Status at step $iRow</p>\n";
|
||||
$aCurrentDataSet = array();
|
||||
foreach($aFound as $iObj => $oObj)
|
||||
{
|
||||
$aObjDesc = array(
|
||||
'Status' => (in_array($iObj, $aErrors_Unexpected) ? 'unexpected' : 'ok'),
|
||||
'Object' => $oObj->GetHyperLink()
|
||||
);
|
||||
foreach($aTargetAttributes as $iCol => $sAttCode)
|
||||
{
|
||||
$aObjDesc[$sAttCode] = $oObj->Get($sAttCode);
|
||||
}
|
||||
$aCurrentDataSet[] = $aObjDesc;
|
||||
}
|
||||
if (count($aExpectedObjects) > 0)
|
||||
{
|
||||
foreach($aExpectedObjects as $iExp => $aValues)
|
||||
{
|
||||
$aObjDesc = array(
|
||||
'Status' => 'missing',
|
||||
'Object' => 'n/a'
|
||||
);
|
||||
foreach($aTargetAttributes as $iCol => $sAttCode)
|
||||
{
|
||||
$aObjDesc[$sAttCode] = $aPrefixes[$sAttCode].$aValues[$iCol];
|
||||
}
|
||||
$aCurrentDataSet[] = $aObjDesc;
|
||||
}
|
||||
}
|
||||
echo MyHelpers::make_table_from_assoc_array($aCurrentDataSet);
|
||||
|
||||
if ((count($aErrors_Unexpected) > 0) || (count($aExpectedObjects) > 0))
|
||||
{
|
||||
throw new UnitTestException("The current status in iTop does not match the expectations");
|
||||
}
|
||||
|
||||
// If not on the final row, run a data exchange sequence
|
||||
//
|
||||
if (array_key_exists($iRow, $aSourceData))
|
||||
{
|
||||
$aToBeLoaded = $aSourceData[$iRow];
|
||||
|
||||
$sCsvData = implode(';', $aSourceAttributes)."\n";
|
||||
foreach($aToBeLoaded as $aDataRow)
|
||||
{
|
||||
$aFinalData = array();
|
||||
foreach($aDataRow as $iCol => $value)
|
||||
{
|
||||
if (is_null($value))
|
||||
{
|
||||
$aFinalData[] = '<NULL>';
|
||||
}
|
||||
else
|
||||
{
|
||||
$sAttCode = $aSourceAttributes[$iCol];
|
||||
$aFinalData[] = $aPrefixes[$sAttCode].$value;
|
||||
}
|
||||
}
|
||||
$sCsvData .= implode(';', $aFinalData)."\n";
|
||||
}
|
||||
$aPostData = array('csvdata' => $sCsvData);
|
||||
|
||||
$aImportArgs = array(
|
||||
'data_source_id' => $iDataSourceId,
|
||||
'separator' => ';',
|
||||
'simulate' => 0,
|
||||
'output' => 'details',
|
||||
);
|
||||
|
||||
$aGetParams = array();
|
||||
$aGetParamReport = array();
|
||||
foreach($aImportArgs as $sArg => $sValue)
|
||||
{
|
||||
$aGetParams[] = $sArg.'='.urlencode($sValue);
|
||||
$aGetParamReport[] = $sArg.'='.$sValue;
|
||||
}
|
||||
$sGetParams = implode('&', $aGetParams);
|
||||
$sLogin = isset($aSingleScenario['login']) ? $aSingleScenario['login'] : 'admin';
|
||||
$sPassword = isset($aSingleScenario['password']) ? $aSingleScenario['password'] : 'admin';
|
||||
|
||||
$sRes = self::DoPostRequestAuth('../synchro/synchro_import.php?'.$sGetParams, $aPostData, $sLogin, $sPassword);
|
||||
|
||||
// Report the load results
|
||||
//
|
||||
if (strlen($sCsvData) > 5000)
|
||||
{
|
||||
$sCsvDataViewable = 'INPUT TOO LONG TO BE DISPLAYED ('.strlen($sCsvData).")\n".substr($sCsvData, 0, 500)."\n... TO BE CONTINUED";
|
||||
}
|
||||
else
|
||||
{
|
||||
$sCsvDataViewable = $sCsvData;
|
||||
}
|
||||
$sCsvDataViewable = htmlentities($sCsvDataViewable, ENT_QUOTES, 'UTF-8');
|
||||
|
||||
echo "<div style=\"\">\n";
|
||||
echo " <pre class=\"vardump\">$sCsvDataViewable</pre>\n";
|
||||
echo "</div>\n";
|
||||
|
||||
echo "<pre class=\"vardump\" style=\"clear: both; padding: 15; background-color: black; color: green;\">$sRes</pre>\n";
|
||||
if (stripos($sRes, 'exception') !== false)
|
||||
{
|
||||
throw new UnitTestException('Encountered an Exception during the last import/synchro');
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
||||
echo "</div>\n";
|
||||
}
|
||||
|
||||
protected function DoExecute()
|
||||
{
|
||||
/*
|
||||
$aScenarios = array(
|
||||
array(
|
||||
'desc' => 'Load user logins',
|
||||
'login' => 'admin',
|
||||
'password' => 'admin',
|
||||
'target_class' => 'UserLocal',
|
||||
'full_load_periodicity' => 3600, // should be ignored in this case
|
||||
'reconciliation_policy' => 'use_attributes',
|
||||
'action_on_zero' => 'create',
|
||||
'action_on_one' => 'update',
|
||||
'action_on_multiple' => 'error',
|
||||
'delete_policy' => 'delete',
|
||||
'delete_policy_update' => '',
|
||||
'delete_policy_retention' => 0,
|
||||
'source_data' => array(
|
||||
array('primary_key', 'login', 'password', 'profile_list'),
|
||||
array(
|
||||
array('user_A', 'login_A', 'password_A', 'profileid:10;reason:he/she is managing services'),
|
||||
),
|
||||
),
|
||||
'target_data' => array(
|
||||
array('login'),
|
||||
array(
|
||||
// Initial state
|
||||
),
|
||||
array(
|
||||
array('login_A'),
|
||||
),
|
||||
),
|
||||
'attributes' => array(
|
||||
'login' => array(
|
||||
'do_reconcile' => true,
|
||||
'do_update' => true,
|
||||
'automatic_prefix' => true, // unique id (for unit testing)
|
||||
),
|
||||
'password' => array(
|
||||
'do_reconcile' => false,
|
||||
'do_update' => true,
|
||||
),
|
||||
'profile_list' => array(
|
||||
'do_reconcile' => false,
|
||||
'do_update' => true,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
*/
|
||||
$aScenarios = array(
|
||||
array(
|
||||
'desc' => 'Simple scenario with delete option (and extkey given as org/name)',
|
||||
'login' => 'admin',
|
||||
'password' => 'admin',
|
||||
'target_class' => 'ApplicationSolution',
|
||||
'full_load_periodicity' => 3600, // should be ignored in this case
|
||||
'reconciliation_policy' => 'use_attributes',
|
||||
'action_on_zero' => 'create',
|
||||
'action_on_one' => 'update',
|
||||
'action_on_multiple' => 'error',
|
||||
'delete_policy' => 'delete',
|
||||
'delete_policy_update' => '',
|
||||
'delete_policy_retention' => 0,
|
||||
'source_data' => array(
|
||||
array('primary_key', 'org_id', 'name', 'status'),
|
||||
array(
|
||||
array('obj_A', null, 'obj_A', 'production'), // org_id unchanged
|
||||
array('obj_B', '_DUMMY_', 'obj_B', 'production'), // error, '_DUMMY_' unknown
|
||||
array('obj_C', 'SOMECODE', 'obj_C', 'production'),
|
||||
array('obj_D', null, 'obj_D', 'production'),
|
||||
array('obj_E', '_DUMMY_', 'obj_E', 'production'),
|
||||
),
|
||||
array(
|
||||
),
|
||||
array(
|
||||
),
|
||||
),
|
||||
'target_data' => array(
|
||||
array('org_id', 'name', 'status'),
|
||||
array(
|
||||
// Initial state
|
||||
array(2, 'obj_A', 'production'),
|
||||
array(2, 'obj_B', 'production'),
|
||||
),
|
||||
array(
|
||||
array(2, 'obj_A', 'production'),
|
||||
array(2, 'obj_B', 'production'),
|
||||
array(1, 'obj_C', 'production'),
|
||||
),
|
||||
array(
|
||||
array(2, 'obj_A', 'production'),
|
||||
array(2, 'obj_B', 'production'),
|
||||
// deleted !
|
||||
),
|
||||
// The only diff here is into the log
|
||||
array(
|
||||
array(2, 'obj_A', 'production'),
|
||||
array(2, 'obj_B', 'production'),
|
||||
// deleted !
|
||||
),
|
||||
),
|
||||
'attributes' => array(
|
||||
'org_id' => array(
|
||||
'do_reconcile' => false,
|
||||
'do_update' => true,
|
||||
'reconciliation_attcode' => 'code',
|
||||
),
|
||||
'name' => array(
|
||||
'do_reconcile' => true,
|
||||
'do_update' => true,
|
||||
'automatic_prefix' => true, // unique id
|
||||
),
|
||||
'status' => array(
|
||||
'do_reconcile' => false,
|
||||
'do_update' => true,
|
||||
),
|
||||
),
|
||||
),
|
||||
// );
|
||||
// $aXXXXScenarios = array(
|
||||
array(
|
||||
'desc' => 'Update then delete with retention (to complete with manual testing) and reconciliation on org/name',
|
||||
'login' => 'admin',
|
||||
'password' => 'admin',
|
||||
'target_class' => 'ApplicationSolution',
|
||||
'full_load_periodicity' => 3600,
|
||||
'reconciliation_policy' => 'use_attributes',
|
||||
'action_on_zero' => 'create',
|
||||
'action_on_one' => 'update',
|
||||
'action_on_multiple' => 'error',
|
||||
'delete_policy' => 'update_then_delete',
|
||||
'delete_policy_update' => 'status:obsolete',
|
||||
'delete_policy_retention' => 15,
|
||||
'source_data' => array(
|
||||
array('primary_key', 'org_id', 'name', 'status'),
|
||||
array(
|
||||
array('obj_A', 'Demo', 'obj_A', 'production'),
|
||||
),
|
||||
array(
|
||||
),
|
||||
),
|
||||
'target_data' => array(
|
||||
array('org_id', 'name', 'status'),
|
||||
array(
|
||||
// Initial state
|
||||
),
|
||||
array(
|
||||
array(2, 'obj_A', 'production'),
|
||||
),
|
||||
array(
|
||||
array(2, 'obj_A', 'obsolete'),
|
||||
// deleted !
|
||||
),
|
||||
),
|
||||
'attributes' => array(
|
||||
'org_id' => array(
|
||||
'do_reconcile' => true,
|
||||
'do_update' => true,
|
||||
'reconciliation_attcode' => 'name',
|
||||
),
|
||||
'name' => array(
|
||||
'do_reconcile' => true,
|
||||
'do_update' => true,
|
||||
'automatic_prefix' => true, // unique id
|
||||
),
|
||||
'status' => array(
|
||||
'do_reconcile' => false,
|
||||
'do_update' => true,
|
||||
),
|
||||
),
|
||||
),
|
||||
//);
|
||||
//$aXXScenarios = array(
|
||||
array(
|
||||
'desc' => 'Simple scenario loading a few ApplicationSolution',
|
||||
'login' => 'admin',
|
||||
'password' => 'admin',
|
||||
'target_class' => 'ApplicationSolution',
|
||||
'full_load_periodicity' => 3600,
|
||||
'reconciliation_policy' => 'use_attributes',
|
||||
'action_on_zero' => 'create',
|
||||
'action_on_one' => 'update',
|
||||
'action_on_multiple' => 'error',
|
||||
'delete_policy' => 'update',
|
||||
'delete_policy_update' => 'status:obsolete',
|
||||
'delete_policy_retention' => 0,
|
||||
'source_data' => array(
|
||||
array('primary_key', 'org_id', 'name', 'status'),
|
||||
array(
|
||||
array('obj_A', 2, 'obj_A', 'production'),
|
||||
array('obj_B', 2, 'obj_B', 'implementation'),
|
||||
array('obj_C', 2, 'obj_C', 'implementation'),
|
||||
),
|
||||
array(
|
||||
array('obj_A', 2, 'obj_A', 'production'),
|
||||
array('obj_B', 2, 'obj_B', 'implementation'),
|
||||
array('obj_C', 2, 'obj_C', 'implementation'),
|
||||
),
|
||||
array(
|
||||
array('obj_A', 2, 'obj_A', 'production'),
|
||||
array('obj_C', 2, 'obj_C', 'implementation'),
|
||||
array('obj_D', 2, 'obj_D', 'implementation'),
|
||||
),
|
||||
array(
|
||||
array('obj_C', 2, 'obj_C', 'production'),
|
||||
),
|
||||
array(
|
||||
array('obj_C', 2, 'obj_C', 'production'),
|
||||
),
|
||||
),
|
||||
'target_data' => array(
|
||||
array('org_id', 'name', 'status'),
|
||||
array(
|
||||
// Initial state
|
||||
array(2, 'obj_A', 'implementation'),
|
||||
array(2, 'obj_B', 'production'),
|
||||
array(2, 'obj_B', 'implementation'),
|
||||
),
|
||||
array(
|
||||
array(2, 'obj_A', 'production'),
|
||||
array(2, 'obj_B', 'production'),
|
||||
array(2, 'obj_B', 'implementation'),
|
||||
array(2, 'obj_C', 'implementation'),
|
||||
),
|
||||
array(
|
||||
array(2, 'obj_A', 'production'),
|
||||
array(2, 'obj_B', 'production'),
|
||||
array(2, 'obj_B', 'implementation'),
|
||||
array(2, 'obj_C', 'implementation'),
|
||||
),
|
||||
array(
|
||||
array(2, 'obj_A', 'production'),
|
||||
array(2, 'obj_B', 'production'),
|
||||
array(2, 'obj_B', 'implementation'),
|
||||
array(2, 'obj_C', 'implementation'),
|
||||
array(2, 'obj_D', 'implementation'),
|
||||
),
|
||||
array(
|
||||
array(2, 'obj_A', 'obsolete'),
|
||||
array(2, 'obj_B', 'production'),
|
||||
array(2, 'obj_B', 'implementation'),
|
||||
array(2, 'obj_C', 'production'),
|
||||
array(2, 'obj_D', 'obsolete'),
|
||||
),
|
||||
array(
|
||||
array(2, 'obj_A', 'obsolete'),
|
||||
array(2, 'obj_B', 'production'),
|
||||
array(2, 'obj_B', 'implementation'),
|
||||
array(2, 'obj_C', 'production'),
|
||||
array(2, 'obj_D', 'obsolete'),
|
||||
),
|
||||
),
|
||||
'attributes' => array(
|
||||
'org_id' => array(
|
||||
'do_reconcile' => false,
|
||||
'do_update' => true,
|
||||
),
|
||||
'name' => array(
|
||||
'do_reconcile' => true,
|
||||
'do_update' => true,
|
||||
'automatic_prefix' => true, // unique id
|
||||
),
|
||||
'status' => array(
|
||||
'do_reconcile' => false,
|
||||
'do_update' => true,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
foreach ($aScenarios as $aSingleScenario)
|
||||
{
|
||||
$this->DoExecScenario($aSingleScenario);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Test SOAP services
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -340,11 +340,9 @@ function CronExec($oP, $bVerbose, $bDebug=false)
|
||||
/**
|
||||
* @param \WebPage $oP
|
||||
*/
|
||||
function CheckMaintenanceMode(Page $oP): void
|
||||
{
|
||||
function CheckMaintenanceMode(Page $oP) {
|
||||
// Verify files instead of reloading the full config each time
|
||||
if (file_exists(MAINTENANCE_MODE_FILE) || file_exists(READONLY_MODE_FILE))
|
||||
{
|
||||
if (file_exists(MAINTENANCE_MODE_FILE) || file_exists(READONLY_MODE_FILE)) {
|
||||
$oP->p("Maintenance detected, exiting");
|
||||
exit(EXIT_CODE_ERROR);
|
||||
}
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
if (!defined('__DIR__')) define('__DIR__', dirname(__FILE__));
|
||||
require_once(__DIR__.'/../approot.inc.php');
|
||||
require_once(APPROOT.'/application/application.inc.php');
|
||||
require_once(APPROOT.'/setup/setuppage.class.inc.php');
|
||||
|
||||
|
||||
require_once(APPROOT.'/application/startup.inc.php');
|
||||
|
||||
Reference in New Issue
Block a user