diff --git a/app/components/barra_filtros_combinados.php b/app/components/barra_filtros_combinados.php index f45a28f..ec0fa88 100755 --- a/app/components/barra_filtros_combinados.php +++ b/app/components/barra_filtros_combinados.php @@ -137,7 +137,7 @@
- +
@@ -247,7 +247,16 @@ function toggle_filtro_combinado() $("#form_lista").attr('action', ''); $("#form_lista").attr('method', 'get'); $("#form_lista").submit(); -} -); +}); + +$(document).on('click', "#btn_limpar_filtro_combinado", function() +{ + $("#filtros_disponiveis").empty(); + va_filtros_busca.push = []; + va_contador_filtros_busca = []; + + $("#form_lista").submit(); + +}); \ No newline at end of file diff --git a/app/components/barra_visualizacoes.php b/app/components/barra_visualizacoes.php index 3f547ac..0625785 100644 --- a/app/components/barra_visualizacoes.php +++ b/app/components/barra_visualizacoes.php @@ -12,6 +12,12 @@ "campo" => "recurso_sistema_codigo", "atributo" => "visualizacao_recurso_sistema_codigo" ] + ], + "filtro" => [ + [ + "atributo" => "visualizacao_habilitado", + "valor" => 1 + ] ] ]; diff --git a/app/components/importar_instrucoes.php b/app/components/importar_instrucoes.php new file mode 100755 index 0000000..37e3cb9 --- /dev/null +++ b/app/components/importar_instrucoes.php @@ -0,0 +1,189 @@ + "import_debug", + "label" => "Modo teste", + "description" => "Nenhuma alteração é feita no banco de dados durante a importação e o relatório da importação é exibido ao final.", + "value" => true, + "type" => "checkbox" + ]; + + $va_import_config["import_allow_errors"] = [ + "name" => "import_allow_errors", + "label" => "Tolerância a erros", + "description" => "Caso alguma célula possua um valor inválido e não possa ser processada, o item será criado sem o valor da célula.", + "value" => true, + "type" => "checkbox" + ]; + + $va_import_config["import_upsert"] = [ + "name" => "import_mode", + "label" => "Criar e atualizar itens", + "description" => "Criar novos itens no banco de dados, caso não existam. Atualizar itens existentes no banco de dados, caso existam. O identificador do item deve estar presente no arquivo de importação para atualização.", + "value" => "upsert", + "type" => "radio", + "checked" => "checked" + ]; + + $va_import_config["import_create"] = [ + "name" => "import_mode", + "label" => "Somente criar itens", + "description" => "Criar novos itens no banco de dados, caso não existam.", + "value" => "create", + "type" => "radio" + ]; + + $va_import_config["import_update"] = [ + "name" => "import_mode", + "label" => "Somente atualizar itens", + "description" => "Atualizar itens existentes no banco de dados, caso existam. O identificador do item deve estar presente no arquivo de importação.", + "value" => "update", + "type" => "radio" + ]; + + $va_import_config["import_delete"] = [ + "name" => "import_mode", + "label" => "Apagar e recriar itens", + "description" => "Caso existam itens no banco de dados, eles serão apagados e recriados com os dados do arquivo de importação. O identificador do item deve estar presente no arquivo de importação.", + "value" => "delete", + "type" => "radio" + ]; + + $va_import_config["import_default_value"] = [ + "name" => "import_default_value", + "description" => "Valor padrão a ser utilizado caso o campo não esteja preenchido no arquivo de importação.", + "label" => "Valor padrão", + "type" => "text", + "value" => "", + "fields" => [] + ]; + + $va_import_config["import_create_related"] = [ + "name" => "import_create_related", + "label" => "Criar novos itens relacionados", + "description" => "Caso o item relacionado não exista no banco de dados, será criado.", + "value" => 1, + "type" => "checkbox", + "fields" => [ + "html_autocomplete", + ] + ]; + + $va_import_config["import_relation_type"] = [ + "name" => "import_relation_type", + "label" => "Tipo de relação padrão", + "description" => "Tipo de relação a ser estabelecida entre os itens relacionados.", + "value" => "", + "type" => "select", + "fields" => [ + "html_autocomplete" + ] + ]; + + $va_import_config["import_separator"] = [ + "name" => "import_separator", + "label" => "Separador de valores", + "description" => "Caractere utilizado para separar os valores de um campo.", + "value" => "", + "type" => "text", + "fields" => [ + "autocomplete_input", + "multi_check_input", + "multi_fields_input" + ] + ]; + + $va_import_config["import_separator_subfield"] = [ + "name" => "import_separator_subfield", + "label" => "Separador de subcampos", + "description" => "Caractere utilizado para separar os subcampos.", + "value" => "", + "type" => "text", + "fields" => [ + "multi_fields_input", + ] + ]; + + $va_import_config["import_separator_hierarchy"] = [ + "name" => "import_separator_hierarchy", + "label" => "Separador de hierarquia", + "description" => "Caractere utilizado para separar os níveis de hierarquia.", + "value" => "", + "type" => "text" + ]; + + return $va_import_config; + } + $va_fields_import_options = get_import_config_options(); +?> + +
+

Opções de importação

+ + + + + + + + + + $va_option) : ?> + + + + + + + + +
OpçãoDescriçãoValor
+ " + type="" + name="parametros_importacao[]" + value="" + > +
+ + +

Instruções

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
IdentificadorNomeDescriçãoAutoria...
1Nome 1Descrição 1Autoria 1; Autoria 2...
2Nome 2Descrição 2Autoria 3...
+
\ No newline at end of file diff --git a/app/components/ler_valor.php b/app/components/ler_valor.php index 6b4b694..463ed6a 100644 --- a/app/components/ler_valor.php +++ b/app/components/ler_valor.php @@ -204,6 +204,14 @@ function ler_valor1($ps_atributo, $pa_item, $pa_opcoes_campo=null, $pn_numero_it $vs_expressao_montada = '' . $vs_expressao_montada . ''; } + elseif (isset($pa_opcoes_campo["formato"]["link"]["get_link"])) + { + $vo_objeto = new $pa_opcoes_campo["formato"]["link"]["objeto"]; + + $vn_objeto_link_codigo = $va_atributo_temp[$pa_opcoes_campo["formato"]["link"]["codigo"]]; + + $vs_expressao_montada = $vo_objeto->get_link($vn_objeto_link_codigo, $vs_expressao_montada); + } else { $vs_expressao_montada = '' . $vs_expressao_montada . ''; diff --git a/app/components/listagem.php b/app/components/listagem.php index 0e9e172..283d54d 100644 --- a/app/components/listagem.php +++ b/app/components/listagem.php @@ -224,7 +224,7 @@ } ?> - registros_protegidos)) { ?> Substituir @@ -232,7 +232,7 @@ } ?> - registros_protegidos)) { ?> Excluir diff --git a/app/editar.php b/app/editar.php index f76b3c4..98958f3 100644 --- a/app/editar.php +++ b/app/editar.php @@ -44,6 +44,8 @@ foreach ($vo_objeto->controlador_acesso as $vs_parametro_controlador => $vs_atributo_controlador) { + if ($va_parametros_controle_acesso[$vs_parametro_controlador] == "_ALL_") continue; + if ((trim($va_parametros_controle_acesso[$vs_parametro_controlador]) == "") && ($vo_objeto->get_chave_primaria()[0] != $vs_parametro_controlador)) { if (!isset($va_parametros_controle_acesso["_combinacao_"]) || (isset($va_parametros_controle_acesso["_combinacao_"]) && $va_parametros_controle_acesso["_combinacao_"] != "OR") ) diff --git a/app/functions/autenticar_usuario.php b/app/functions/autenticar_usuario.php index 81e63ed..7cb2491 100644 --- a/app/functions/autenticar_usuario.php +++ b/app/functions/autenticar_usuario.php @@ -343,6 +343,7 @@ $va_usuario_logado_especies_documentais = array(); + if (isset($va_usuario["usuario_especie_documental_codigo"])) { foreach ($va_usuario["usuario_especie_documental_codigo"] as $va_especie_documental) @@ -350,6 +351,8 @@ $va_usuario_logado_especies_documentais[] = $va_especie_documental["usuario_especie_documental_codigo"]['especie_documental_codigo']; } } + elseif ($vn_usuario_logado_acervo_codigo) + $va_usuario_logado_especies_documentais[] = "_ALL_"; $vn_usuario_logado_especie_documental_codigo = join("|", $va_usuario_logado_especies_documentais); diff --git a/app/functions/autocomplete.php b/app/functions/autocomplete.php index 57be312..b31cae8 100644 --- a/app/functions/autocomplete.php +++ b/app/functions/autocomplete.php @@ -427,7 +427,7 @@ if ( $vb_aplicar_controle_acesso && (in_array($va_parametros_campo["atributos"][0], array_keys($va_parametros_controle_acesso))) ) { - if ($va_parametros_controle_acesso[$va_parametros_campo["atributos"][0]] != "") + if (!in_array($va_parametros_controle_acesso[$va_parametros_campo["atributos"][0]], ["", "_ALL_"])) $va_termo_busca[$va_parametros_campo["atributos"][0]] = $va_parametros_controle_acesso[$va_parametros_campo["atributos"][0]]; } //elseif (isset($va_termo_busca[$va_parametros_campo["nome"]])) diff --git a/app/functions/excluir.php b/app/functions/excluir.php index 4e7e360..e7e1e9b 100644 --- a/app/functions/excluir.php +++ b/app/functions/excluir.php @@ -20,7 +20,7 @@ $vo_objeto = new $vs_id_objeto(''); - if (!$vo_objeto->validar_acesso_registro($vn_codigo_objeto, $va_parametros_controle_acesso)) + if (!$vo_objeto->validar_acesso_registro($vn_codigo_objeto, $va_parametros_controle_acesso) || in_array($vn_codigo_objeto, $vo_objeto->registros_protegidos)) { utils::log( "Tentativa de exclusão sem permissão: ", diff --git a/app/functions/exportar.php b/app/functions/exportar.php index 1cb74aa..67b5311 100644 --- a/app/functions/exportar.php +++ b/app/functions/exportar.php @@ -20,6 +20,11 @@ } $vn_pagina_atual = 1; +$vb_retornar_valores_vazios = true; + + +$vs_visualizacao = "ficha"; + require dirname(__FILE__). "/montar_listagem.php"; $vs_file_path = config::get(["pasta_media", "temp"]) . $vs_file_name; @@ -28,6 +33,8 @@ $vr_file = fopen($vs_file_path, "w"); +create_header($vr_file, $va_itens_listagem ?? []); + add_to_csv($vr_file, $va_itens_listagem ?? []); for ($vn_pagina_atual = 2; $vn_pagina_atual <= $vn_numero_maximo_paginas; $vn_pagina_atual++) @@ -44,21 +51,54 @@ utils::clear_temp_folder("-5 minutes"); exit(); -function add_to_csv($pr_file, $pa_itens_listagem) +function add_to_csv($pr_file, $pa_itens_listagem, $pb_adicionar_cabecalho = false) { + $vn_contador = 1; + foreach ($pa_itens_listagem as $va_item_listagem) { $va_atributos = array(); + $va_atributos[] = $va_item_listagem["id_field"] ?? ""; + $va_atributos[] = $va_item_listagem["main_field"] ?? ""; + /*$va_atributos[] = $va_item_listagem["descriptive_field"] ?? "";*/ + foreach($va_item_listagem["atributos"] as $va_atributos_item_listagem) { - if ($va_atributos_item_listagem["valor"] != "" && $va_atributos_item_listagem["exibir"]) + if ($va_atributos_item_listagem["exibir"] && $va_atributos_item_listagem["exibir"] != 0) { $va_atributos[] = $va_atributos_item_listagem["valor"]; } } fputcsv($pr_file, $va_atributos); + + $vn_contador++; + } +} + +function create_header($pr_file, $pa_itens_listagem) +{ + foreach ($pa_itens_listagem as $va_item_listagem) + { + $va_labels = array(); + + $va_labels[] = $va_item_listagem["id_field_label"] ?? ""; + $va_labels[] = $va_item_listagem["main_field_label"] ?? ""; + /*$va_labels[] = $va_item_listagem["descriptive_field_label"] ?? "";*/ + + foreach($va_item_listagem["atributos"] as $key => $va_atributos_item_listagem) + { + if ($va_atributos_item_listagem["exibir"] && $va_atributos_item_listagem["exibir"] != 0) + { + $va_labels[] = $va_atributos_item_listagem["label"]; + } + + } + + fputcsv($pr_file, $va_labels); + + break; } } diff --git a/app/functions/ler_registros_filhos.php b/app/functions/ler_registros_filhos.php index 2f7d78f..61f4810 100644 --- a/app/functions/ler_registros_filhos.php +++ b/app/functions/ler_registros_filhos.php @@ -24,7 +24,7 @@ $vn_objeto_codigo = $va_parametros['cod']; $vo_objeto = new $vs_id_objeto; - $va_registros_filhos = $vo_objeto->ler_lista([$vo_objeto->get_campo_hierarquico() => $vn_objeto_codigo], "navegacao"); + $va_registros_filhos = $vo_objeto->ler_lista([$vo_objeto->get_campo_hierarquico() => $vn_objeto_codigo], "navegacao", null, null, null, null, null, 1, false); $va_visualizacao_lista = $vo_objeto->get_visualizacao("navegacao"); diff --git a/app/functions/montar_campos.php b/app/functions/montar_campos.php index dcb2489..a1cd110 100755 --- a/app/functions/montar_campos.php +++ b/app/functions/montar_campos.php @@ -180,7 +180,7 @@ { if ( $vb_aplicar_controle_acesso && (in_array($va_parametros_campo["atributo"], array_keys($va_parametros_controle_acesso))) ) { - if ($va_parametros_controle_acesso[$va_parametros_campo["atributo"]] != "") + if (!in_array($va_parametros_controle_acesso[$va_parametros_campo["atributo"]], ["", "_ALL_"])) $va_objeto[$va_parametros_campo["atributo"]] = $va_parametros_controle_acesso[$va_parametros_campo["atributo"]]; } elseif (isset($va_objeto[$va_parametros_campo["nome"]])) diff --git a/app/functions/montar_filtros_busca.php b/app/functions/montar_filtros_busca.php index f32badb..49be1eb 100755 --- a/app/functions/montar_filtros_busca.php +++ b/app/functions/montar_filtros_busca.php @@ -294,6 +294,8 @@ { if ( (in_array($vs_key_controlador, array_keys($va_parametros_controle_acesso))) ) { + if ($va_parametros_controle_acesso[$vs_key_controlador] == "_ALL_") continue; + if ($va_parametros_controle_acesso[$vs_key_controlador] != "") { if (count(explode("|", $va_parametros_controle_acesso[$vs_key_controlador])) == 1 && isset($va_campos[$vs_atributo_controlador])) diff --git a/app/functions/montar_listagem.php b/app/functions/montar_listagem.php index 7d1a835..bbf1e71 100644 --- a/app/functions/montar_listagem.php +++ b/app/functions/montar_listagem.php @@ -65,6 +65,9 @@ if (!isset($vs_ordem)) $vs_ordem = ""; + if (!isset($vb_retornar_valores_vazios)) + $vb_retornar_valores_vazios = false; + // Eis aqui: onde o objeto_base vai montar automaticamente os atributos, campos e visualizações do // objeto passado por parâmetro no construtor ////////////////////////////////////////////////////////////////////////////////////////////////// @@ -202,8 +205,8 @@ } else $vn_numero_registros_lista = $vn_numero_registros; - - $va_objetos_lista = $vo_objeto->ler_lista($va_parametros_filtros_consulta, $vs_visualizacao, $vn_primeiro_registro, $vn_numero_registros_lista, $vn_ordenacao, $vs_ordem, $va_log_info); + + $va_objetos_lista = $vo_objeto->ler_lista($va_parametros_filtros_consulta, $vs_visualizacao, $vn_primeiro_registro, $vn_numero_registros_lista, $vn_ordenacao, $vs_ordem, $va_log_info, 1, $vb_retornar_ramos_inferiores ?? true); if ($vs_formato_listagem == "default") { @@ -310,7 +313,10 @@ $vs_valor_atributo = ler_valor1($vs_key_campo_visualizacao, $va_item, $va_campo_visualizacao); if ($vb_id_field) + { $va_item_listagem["id_field"] = $vs_valor_atributo; + $va_item_listagem["id_field_label"] = $vs_label_campo; + } elseif ($vb_main_field) { @@ -318,14 +324,20 @@ $va_item_listagem["main_field"] = $vs_valor_atributo; elseif ($vs_valor_atributo != "") $va_item_listagem["main_field"] = $va_item_listagem["main_field"] . ": " . $vs_valor_atributo; + + $va_item_listagem["main_field_label"] = $vs_label_campo; } elseif ($vb_descriptive_field) + { $va_item_listagem["descriptive_field"] = $vs_valor_atributo; + $va_item_listagem["descriptive_field_label"] = $vs_label_campo; + } + if ( ($vs_output == "out") || (!$vb_id_field && !$vb_main_field && !$vb_descriptive_field) ) { - if ($vs_valor_atributo != "") - { + /* if ($vs_valor_atributo != "") + { */ $va_atributo_item_listagem["label"] = $vs_label_campo; $va_atributo_item_listagem["valor"] = $vs_valor_atributo; @@ -341,7 +353,7 @@ $va_atributos_item_listagem[] = $va_atributo_item_listagem; - } + // } } } diff --git a/app/importar.php b/app/importar.php old mode 100644 new mode 100755 index 270a3d0..0d15ae9 --- a/app/importar.php +++ b/app/importar.php @@ -1,7 +1,151 @@ inicializar_campos_edicao_objeto_importacao(); + +switch ($vn_step) +{ + case 1: + break; + case 2: + $vo_importacao->set_caminho_arquivo_importacao(move_import_file()); + $vo_importacao->set_campos_origem_label(get_file_data($vo_importacao->get_caminho_arquivo_importacao(), true)[0]); + break; + case 3: + $vo_importacao->set_campos_origem_label(get_file_data($vo_importacao->get_caminho_arquivo_importacao(),true)[0]); + $vo_importacao->set_parametros_importacao($_POST["parametros_importacao"] ?? []); + $vo_importacao->set_campos_destino_selecao(json_decode($vs_campos_destino_selecao_json, true)); + break; + case 4: + $vo_importacao->set_campos_origem_label(get_file_data($vo_importacao->get_caminho_arquivo_importacao(),true)[0]); + $vo_importacao->set_parametros_importacao($_POST["parametros_importacao"] ?? []); + $vo_importacao->set_campos_destino_selecao(json_decode($vs_campos_destino_selecao_json, true)); + $vo_importacao->inicializar_variantes_campos_importacao( + $_POST["campos_valor_padrao"] ?? [], + $_POST["campos_criar_itens_relacionados"] ?? [], + $_POST["campos_separador"] ?? [], + $_POST["campos_subcampos_separador"] ?? [], + ); + $vo_importacao->set_dados_origem(get_file_data($vo_importacao->get_caminho_arquivo_importacao())); + $va_resultado_importacao = $vo_importacao->importar(); + break; +} + +function get_file_data($ps_caminho_arquivo, $pb_return_only_headers = false, $pb_remove_header = true): array +{ + $vs_extensao_arquivo = pathinfo($ps_caminho_arquivo, PATHINFO_EXTENSION); + $va_rows = []; + + if ($vs_extensao_arquivo == "xlsx" || $vs_extensao_arquivo == "xls") + { + $xlsx = SimpleXLSX::parse($ps_caminho_arquivo); + if (!$xlsx) { return []; } + + if ($pb_return_only_headers) + { + $va_rows = iterator_to_array($xlsx->readRows(0, 1)); + } + else + { + $va_rows = iterator_to_array($xlsx->readRows()); + if ($pb_remove_header) + { + unset($va_rows[0]); + } + } + } + else if ($vs_extensao_arquivo == "csv") + { + if ($pb_return_only_headers) + { + $va_rows = get_data_csv($ps_caminho_arquivo, ",", 1); + } + else + { + $va_rows = get_data_csv($ps_caminho_arquivo, ",", 0, true); + } + } + + return $va_rows; +} + +function move_import_file(): string +{ + $vs_pasta_import = config::get(["pasta_media", "temp"]); + if (!isset($_FILES["arquivo"]) || $_FILES["arquivo"]["error"] != UPLOAD_ERR_OK) + { + return ""; + } + + $va_arquivo = $_FILES["arquivo"]; + $vs_caminho_arquivo = $vs_pasta_import . utils::sanitize_file_name($va_arquivo["name"]); + + if (move_uploaded_file($va_arquivo["tmp_name"], $vs_caminho_arquivo)) + { + return $vs_caminho_arquivo; + } + + return ""; +} + +function get_data_csv($ps_file_path, $ps_delimiter = ",", $pn_limit_num_rows = 0, $pb_remove_header = false, $pb_assign_header_labels_on_cols = false): array +{ + // TODO: Alguns documentos de entrada podem conter colunas fantasma. Melhorar essa funcao futuramente pra evitar rows de insercao inválidas + $handle = fopen($ps_file_path, "r"); + $rows = array(); + + if ($handle !== false) + { + $row = 0; + while (($data = fgetcsv($handle, 0, $ps_delimiter)) !== false) + { + if ($pb_assign_header_labels_on_cols && !$pb_remove_header && $row != 0) + { + $rows[] = array_combine($rows[0], $data); + } + else + { + $rows[] = $data; + } + + $row++; + if ($pn_limit_num_rows > 0 && $row >= $pn_limit_num_rows) + { + break; + } + } + fclose($handle); + } + + if ($pb_remove_header) + { + unset($rows[0]); + } + + return $rows; +} + +function get_chave_parametro($ps_chave, $pa_parametro) +{ + return current(array_filter(array_keys($pa_parametro), function ($vs_chave_parametro) use ($ps_chave) + { + return strpos($vs_chave_parametro, $ps_chave); + })); +} ?> @@ -12,113 +156,319 @@ - +
- +
-
Importar
- +
Importar
-
- - -
-
-
- - > Substituir valores + + + + +
+
+
+ +
-
-
-
- + + +
+
+ +
+
+ + + + + get_caminho_arquivo_importacao() == "" || count($vo_importacao->get_campos_origem_label()) == 0) : ?> + + +
+ +
+ +
+ + + + +

Relacionamento de campos

+ + + + + + + + + get_campos_origem_label() as $vn_campo_origem_atual => $vs_campo_origem) : ?> + + + + + + + +
Coluna de origemCampo de destino
+ +
+ +
+
+ +
+
+
+ + + +
+

Definição de variáveis de importação

+ + + + + + + + + + + + + + + + + + + + get_campos_destino_selecao() as $vn_index_campo_destino => $va_campo_destino): ?> + get_campo_origem_label($vn_index_campo_destino); + $vs_label_campo_destino_atual = $vo_importacao->get_campo_destino_selecao($vn_index_campo_destino); + $va_campo_destino_atual = $vo_importacao->get_campo_edicao($vs_label_campo_destino_atual); + ?> + + + + + + + + + + + +
Coluna de origemCampo de destino selecionadoValor padrãoCriar novos itens relacionados?Tipo de relação padrãoSeparador de valoresSeparador de subcampos
+ () + + ler_numero_registros([""])) < 100): ?> + ler_lista(); + ?> + + + + + + + + + + + + + + + +
+
+
+ +
+
+ +
+

Conclusão de importação.

+ + + + + + + + + + + + + + + + + + + +
Modo importaçãoObjeto importaçãoDuraçãoDebug ativo?Tolerância de erros?
+ + + + + + + + + +
+ + + + + + + + + + + $va_dados_operacao) : + ?> + + + + + + + + + +
NumeroTipo de operaçãoResultadoAcesso
+ + + + + + + ' . $va_dados_operacao["codigo_registro"] . '' : + $va_dados_operacao["mensagens"][0]; + ?> +
- - -
- importar($va_atributos, $vn_usuario_logado_codigo, $vb_sobrescrever_valores); - - if ($contador_linhas > 1) - print ", "; - - print trim($va_atributos[0]); - @ob_flush(); - flush(); - - $contador_linhas++; - } - - if (!feof($v_file)) - { - echo "Erro: falha na leitura do arquivo!\n"; - } - - fclose($v_file); - } - } - ?> -
+
- - -
+ + - \ No newline at end of file + + \ No newline at end of file diff --git a/app/listar.php b/app/listar.php index e102963..65fd4a4 100755 --- a/app/listar.php +++ b/app/listar.php @@ -143,7 +143,7 @@ } ?> - diff --git a/app/substituir.php b/app/substituir.php index fd1636e..ce4829c 100644 --- a/app/substituir.php +++ b/app/substituir.php @@ -22,7 +22,7 @@ $vo_objeto = new $vs_id_objeto_tela($vs_id_objeto_tela); - if (!$vo_objeto->validar_acesso_registro($vn_objeto_codigo, $va_parametros_controle_acesso)) + if (!$vo_objeto->validar_acesso_registro($vn_objeto_codigo, $va_parametros_controle_acesso) || in_array($vn_objeto_codigo, $vo_objeto->registros_protegidos)) { print "Sem permissão para substituir este registro."; exit(); @@ -85,6 +85,7 @@ $vs_atributo_codigo = ""; $vs_atributo_nome = ""; $vs_procurar_por = ""; + $vb_permitir_cadastro = true; switch($vs_id_objeto_tela) { @@ -92,6 +93,7 @@ $vs_campo_nome = "agrupamento"; $vs_atributo_codigo = "agrupamento_codigo"; $vs_atributo_nome = "agrupamento_dados_textuais_0_agrupamento_nome"; + $vb_permitir_cadastro = false; break; @@ -174,6 +176,13 @@ break; + case "unidade_armazenamento": + $vs_atributo_codigo = "unidade_armazenamento_codigo"; + $vs_atributo_nome = "unidade_armazenamento_nome"; + $vb_permitir_cadastro = false; + + break; + default: $vb_substituir_disponivel = false; } @@ -252,7 +261,7 @@ "multiplos_valores" => false, "procurar_por" => $vs_procurar_por, "visualizacao" => "lista", - "permitir_cadastro" => true, + "permitir_cadastro" => $vb_permitir_cadastro, "campo_salvar" => $vs_atributo_nome, "excluir" => $vn_objeto_codigo ]; diff --git a/src/lib/business b/src/lib/business index bb5b1d2..1ade496 160000 --- a/src/lib/business +++ b/src/lib/business @@ -1 +1 @@ -Subproject commit bb5b1d25c8873414f52471033a22989f26e30e82 +Subproject commit 1ade496465191e03e2f2c39c34c0edc614c1ae79 diff --git a/src/lib/default/auxiliary/formato_data.php b/src/lib/default/auxiliary/formato_data.php index cd2ccb1..78a289e 100755 --- a/src/lib/default/auxiliary/formato_data.php +++ b/src/lib/default/auxiliary/formato_data.php @@ -27,7 +27,7 @@ public function ler($pn_codigo, $ps_visualizacao = 'lista', $pn_idioma_codigo = return $va_resultado; } - public function ler_lista($pa_filtros_busca = null, $ps_visualizacao = "lista", $pn_primeiro_registro = 0, $pn_numero_registros = 20, $pa_order_by = null, $ps_order = null, $pa_log_info = null, $pn_idioma_codigo = 1) + public function ler_lista($pa_filtros_busca = null, $ps_visualizacao = "lista", $pn_primeiro_registro = 0, $pn_numero_registros = 20, $pa_order_by = null, $ps_order = null, $pa_log_info = null, $pn_idioma_codigo = 1, $pb_retornar_ramos_inferiores = true) { $va_itens = array(); $va_resultado = array(); diff --git a/src/lib/default/auxiliary/situacao_acervo.php b/src/lib/default/auxiliary/situacao_acervo.php index 0c3360c..65ea750 100644 --- a/src/lib/default/auxiliary/situacao_acervo.php +++ b/src/lib/default/auxiliary/situacao_acervo.php @@ -27,7 +27,7 @@ public function ler($pn_codigo, $ps_visualizacao = 'lista', $pn_idioma_codigo = return $va_resultado; } - public function ler_lista($pa_filtros_busca = null, $ps_visualizacao = "lista", $pn_primeiro_registro = 0, $pn_numero_registros = 20, $pa_order_by = null, $ps_order = null, $pa_log_info = null, $pn_idioma_codigo = 1) + public function ler_lista($pa_filtros_busca = null, $ps_visualizacao = "lista", $pn_primeiro_registro = 0, $pn_numero_registros = 20, $pa_order_by = null, $ps_order = null, $pa_log_info = null, $pn_idioma_codigo = 1, $pb_retornar_ramos_inferiores = true) { $va_itens = array(); $va_resultado = array(); diff --git a/src/lib/default/auxiliary/tipo_acervo.php b/src/lib/default/auxiliary/tipo_acervo.php index 003409f..817c305 100644 --- a/src/lib/default/auxiliary/tipo_acervo.php +++ b/src/lib/default/auxiliary/tipo_acervo.php @@ -30,7 +30,7 @@ public function ler($pn_codigo, $ps_visualizacao = 'lista', $pn_idioma_codigo = return $va_resultado; } - public function ler_lista($pa_filtros_busca = null, $ps_visualizacao = "lista", $pn_primeiro_registro = 0, $pn_numero_registros = 20, $pa_order_by = null, $ps_order = null, $pa_log_info = null, $pn_idioma_codigo = 1) + public function ler_lista($pa_filtros_busca = null, $ps_visualizacao = "lista", $pn_primeiro_registro = 0, $pn_numero_registros = 20, $pa_order_by = null, $ps_order = null, $pa_log_info = null, $pn_idioma_codigo = 1, $pb_retornar_ramos_inferiores = true) { $va_itens = array(); $va_resultado = array(); diff --git a/src/lib/default/auxiliary/tipo_endereco.php b/src/lib/default/auxiliary/tipo_endereco.php index e00365f..2ae4ed4 100644 --- a/src/lib/default/auxiliary/tipo_endereco.php +++ b/src/lib/default/auxiliary/tipo_endereco.php @@ -24,7 +24,7 @@ public function ler($pn_codigo, $ps_visualizacao = 'lista', $pn_idioma_codigo = return $va_resultado; } - public function ler_lista($pa_filtros_busca = null, $ps_visualizacao = 'lista', $pn_primeiro_registro = 0, $pn_numero_registros = 0, $pa_order_by = null, $ps_order = null, $pa_log_info = null, $pn_idioma_codigo = 1) + public function ler_lista($pa_filtros_busca = null, $ps_visualizacao = 'lista', $pn_primeiro_registro = 0, $pn_numero_registros = 0, $pa_order_by = null, $ps_order = null, $pa_log_info = null, $pn_idioma_codigo = 1, $pb_retornar_ramos_inferiores = true) { $va_itens = array(); $va_resultado = array(); diff --git a/src/lib/default/auxiliary/tipo_entidade.php b/src/lib/default/auxiliary/tipo_entidade.php index 919d7a8..779eedc 100644 --- a/src/lib/default/auxiliary/tipo_entidade.php +++ b/src/lib/default/auxiliary/tipo_entidade.php @@ -30,7 +30,7 @@ public function ler($pn_codigo, $ps_visualizacao = 'lista', $pn_idioma_codigo = return $va_resultado; } - public function ler_lista($pa_filtros_busca = null, $ps_visualizacao = "lista", $pn_primeiro_registro = 0, $pn_numero_registros = 20, $pa_order_by = null, $ps_order = null, $pa_log_info = null, $pn_idioma_codigo = 1) + public function ler_lista($pa_filtros_busca = null, $ps_visualizacao = "lista", $pn_primeiro_registro = 0, $pn_numero_registros = 20, $pa_order_by = null, $ps_order = null, $pa_log_info = null, $pn_idioma_codigo = 1, $pb_retornar_ramos_inferiores = true) { $va_itens = array(); $va_resultado = array(); diff --git a/src/lib/default/auxiliary/tipo_incorporacao.php b/src/lib/default/auxiliary/tipo_incorporacao.php index 9c65654..6be96f7 100644 --- a/src/lib/default/auxiliary/tipo_incorporacao.php +++ b/src/lib/default/auxiliary/tipo_incorporacao.php @@ -24,7 +24,7 @@ public function ler($pn_codigo, $ps_visualizacao = 'lista', $pn_idioma_codigo = return $va_resultado; } - public function ler_lista($pa_filtros_busca = null, $ps_visualizacao = "lista", $pn_primeiro_registro = 0, $pn_numero_registros = 20, $pa_order_by = null, $ps_order = null, $pa_log_info = null, $pn_idioma_codigo = 1) + public function ler_lista($pa_filtros_busca = null, $ps_visualizacao = "lista", $pn_primeiro_registro = 0, $pn_numero_registros = 20, $pa_order_by = null, $ps_order = null, $pa_log_info = null, $pn_idioma_codigo = 1, $pb_retornar_ramos_inferiores = true) { $va_itens = array(); $va_resultado = array(); diff --git a/src/lib/default/core/biblioteca.php b/src/lib/default/core/biblioteca.php index 9e4ae65..a6df682 100644 --- a/src/lib/default/core/biblioteca.php +++ b/src/lib/default/core/biblioteca.php @@ -265,7 +265,7 @@ public function inicializar_visualizacoes() ]; } - public function ler_numero_registros($pa_filtros_busca = null, $pa_log_info = null) + public function ler_numero_registros($pa_filtros_busca = null, $pa_log_info = null, $pb_retornar_ramos_inferiores = true) { if (isset($pa_filtros_busca["instituicao_codigo"])) $pa_filtros_busca["acervo_codigo_0_acervo_instituicao_codigo"] = $pa_filtros_busca["instituicao_codigo"]; @@ -273,7 +273,7 @@ public function ler_numero_registros($pa_filtros_busca = null, $pa_log_info = nu return parent::ler_numero_registros($pa_filtros_busca, $pa_log_info); } - public function ler_lista($pa_filtros_busca = null, $ps_visualizacao = "lista", $pn_primeiro_registro = 0, $pn_numero_registros = 20, $pa_order_by = null, $ps_order = null, $pa_log_info = null, $pn_idioma_codigo = 1) + public function ler_lista($pa_filtros_busca = null, $ps_visualizacao = "lista", $pn_primeiro_registro = 0, $pn_numero_registros = 20, $pa_order_by = null, $ps_order = null, $pa_log_info = null, $pn_idioma_codigo = 1, $pb_retornar_ramos_inferiores = true) { if (isset($pa_filtros_busca["instituicao_codigo"])) $pa_filtros_busca["acervo_codigo_0_acervo_instituicao_codigo"] = $pa_filtros_busca["instituicao_codigo"]; diff --git a/src/lib/default/core/conjunto_documental.php b/src/lib/default/core/conjunto_documental.php index cc5333f..cf1ed43 100644 --- a/src/lib/default/core/conjunto_documental.php +++ b/src/lib/default/core/conjunto_documental.php @@ -429,7 +429,7 @@ public function inicializar_visualizacoes() ]; } - public function ler_numero_registros($pa_filtros_busca = null, $pa_log_info = null) + public function ler_numero_registros($pa_filtros_busca = null, $pa_log_info = null, $pb_retornar_ramos_inferiores = true) { if (isset($pa_filtros_busca["instituicao_codigo"])) $pa_filtros_busca["acervo_codigo_0_acervo_instituicao_codigo"] = $pa_filtros_busca["instituicao_codigo"]; @@ -437,7 +437,7 @@ public function ler_numero_registros($pa_filtros_busca = null, $pa_log_info = nu return parent::ler_numero_registros($pa_filtros_busca, $pa_log_info); } - public function ler_lista($pa_filtros_busca = null, $ps_visualizacao = "lista", $pn_primeiro_registro = 0, $pn_numero_registros = 20, $pa_order_by = null, $ps_order = null, $pa_log_info = null, $pn_idioma_codigo = 1) + public function ler_lista($pa_filtros_busca = null, $ps_visualizacao = "lista", $pn_primeiro_registro = 0, $pn_numero_registros = 20, $pa_order_by = null, $ps_order = null, $pa_log_info = null, $pn_idioma_codigo = 1, $pb_retornar_ramos_inferiores = true) { if (isset($pa_filtros_busca["instituicao_codigo"])) $pa_filtros_busca["acervo_codigo_0_acervo_instituicao_codigo"] = $pa_filtros_busca["instituicao_codigo"]; diff --git a/src/lib/default/core/edicao.php b/src/lib/default/core/edicao.php index decb3f0..02f2da1 100755 --- a/src/lib/default/core/edicao.php +++ b/src/lib/default/core/edicao.php @@ -50,7 +50,7 @@ public function ler($pn_codigo, $ps_visualizacao = 'lista', $pn_idioma_codigo = return $va_resultado; } - public function ler_lista($pa_filtros_busca = null, $ps_visualizacao = "lista", $pn_primeiro_registro = 0, $pn_numero_registros = 20, $pa_order_by = null, $ps_order = null, $pa_log_info = null, $pn_idioma_codigo = 1) + public function ler_lista($pa_filtros_busca = null, $ps_visualizacao = "lista", $pn_primeiro_registro = 0, $pn_numero_registros = 20, $pa_order_by = null, $ps_order = null, $pa_log_info = null, $pn_idioma_codigo = 1, $pb_retornar_ramos_inferiores = true) { $va_itens = array(); $va_resultado = array(); diff --git a/src/lib/default/core/grupo.php b/src/lib/default/core/grupo.php index eb059e8..1ef36d1 100755 --- a/src/lib/default/core/grupo.php +++ b/src/lib/default/core/grupo.php @@ -89,7 +89,7 @@ public function ler($pn_codigo, $ps_visualizacao = 'lista', $pn_idioma_codigo = return $va_resultado; } - public function ler_lista($pa_filtros_busca = null, $ps_visualizacao = "lista", $pn_primeiro_registro = 0, $pn_numero_registros = 20, $pa_order_by = null, $ps_order = null, $pa_log_info = null, $pn_idioma_codigo = 1) + public function ler_lista($pa_filtros_busca = null, $ps_visualizacao = "lista", $pn_primeiro_registro = 0, $pn_numero_registros = 20, $pa_order_by = null, $ps_order = null, $pa_log_info = null, $pn_idioma_codigo = 1, $pb_retornar_ramos_inferiores = true) { $va_resultados = parent::ler_lista($pa_filtros_busca, $ps_visualizacao, $pn_primeiro_registro, $pn_numero_registros, $pa_order_by, $ps_order, $pa_log_info, $pn_idioma_codigo); diff --git a/src/lib/default/core/subgrupo.php b/src/lib/default/core/subgrupo.php index c3241b5..2df394a 100755 --- a/src/lib/default/core/subgrupo.php +++ b/src/lib/default/core/subgrupo.php @@ -107,7 +107,7 @@ public function ler($pn_codigo, $ps_visualizacao = 'lista', $pn_idioma_codigo = return $va_resultado; } - public function ler_lista($pa_filtros_busca = null, $ps_visualizacao = "lista", $pn_primeiro_registro = 0, $pn_numero_registros = 20, $pa_order_by = null, $ps_order = null, $pa_log_info = null, $pn_idioma_codigo = 1) + public function ler_lista($pa_filtros_busca = null, $ps_visualizacao = "lista", $pn_primeiro_registro = 0, $pn_numero_registros = 20, $pa_order_by = null, $ps_order = null, $pa_log_info = null, $pn_idioma_codigo = 1, $pb_retornar_ramos_inferiores = true) { $va_resultados = parent::ler_lista($pa_filtros_busca, $ps_visualizacao, $pn_primeiro_registro, $pn_numero_registros, $pa_order_by, $ps_order, $pa_log_info, $pn_idioma_codigo); diff --git a/src/lib/default/core/usuario.php b/src/lib/default/core/usuario.php index fed7b3e..191d31d 100755 --- a/src/lib/default/core/usuario.php +++ b/src/lib/default/core/usuario.php @@ -346,20 +346,20 @@ public function inicializar_visualizacoes() $this->visualizacoes["senha"]["campos"]["usuario_data_expiracao_senha_provisoria"] = ["nome" => "usuario_data_expiracao_senha_provisoria"]; } - public function ler_numero_registros($pa_filtros_busca = null, $pa_log_info = null) + public function ler_numero_registros($pa_filtros_busca = null, $pa_log_info = null, $pb_retornar_ramos_inferiores = true) { if (isset($pa_filtros_busca["instituicao_codigo"])) $pa_filtros_busca["usuario_instituicao_codigo"] = $pa_filtros_busca["instituicao_codigo"]; - return parent::ler_numero_registros($pa_filtros_busca, $pa_log_info); + return parent::ler_numero_registros($pa_filtros_busca, $pa_log_info, $pb_retornar_ramos_inferiores); } - public function ler_lista($pa_filtros_busca = null, $ps_visualizacao = "lista", $pn_primeiro_registro = 0, $pn_numero_registros = 20, $pa_order_by = null, $ps_order = null, $pa_log_info = null, $pn_idioma_codigo = 1, $pb_login = false) + public function ler_lista($pa_filtros_busca = null, $ps_visualizacao = "lista", $pn_primeiro_registro = 0, $pn_numero_registros = 20, $pa_order_by = null, $ps_order = null, $pa_log_info = null, $pn_idioma_codigo = 1, $pb_retornar_ramos_inferiores = true) { if (isset($pa_filtros_busca["instituicao_codigo"])) $pa_filtros_busca["usuario_instituicao_codigo"] = $pa_filtros_busca["instituicao_codigo"]; - return parent::ler_lista($pa_filtros_busca, $ps_visualizacao, $pn_primeiro_registro, $pn_numero_registros, $pa_order_by, $ps_order, $pa_log_info, $pn_idioma_codigo); + return parent::ler_lista($pa_filtros_busca, $ps_visualizacao, $pn_primeiro_registro, $pn_numero_registros, $pa_order_by, $ps_order, $pa_log_info, $pn_idioma_codigo, $pb_retornar_ramos_inferiores); } } diff --git a/src/lib/html/html_filtro_lateral.php b/src/lib/html/html_filtro_lateral.php index cc8f128..547bd54 100755 --- a/src/lib/html/html_filtro_lateral.php +++ b/src/lib/html/html_filtro_lateral.php @@ -3,7 +3,8 @@ class html_filtro_lateral extends html_input { -private $itens; +private $itens = array(); +private $objects = []; public function get_itens() { @@ -13,12 +14,26 @@ public function get_itens() return $this->itens; } +public function get_objects() +{ + return $this->objects; +} + public function preencher($pa_filtro_listagem, $pa_parametros_campo) { $va_itens = array(); + + $va_dependencias = array(); $va_filtro = array(); + $va_filtros_pos_aplicacao = array(); + + $vb_aplicar_filtro_banco_dados = true; - if (isset($pa_filtro_listagem[$pa_parametros_campo["atributo"]]) && is_array($pa_filtro_listagem[$pa_parametros_campo["atributo"]])) + if ( + isset($pa_filtro_listagem[$pa_parametros_campo["atributo"]]) + && + (is_array($pa_filtro_listagem[$pa_parametros_campo["atributo"]]) || $pa_filtro_listagem[$pa_parametros_campo["atributo"]] == 0) + ) { $this->adicionar_item("_NO_", "[Sem atribução]"); return true; @@ -35,14 +50,29 @@ public function preencher($pa_filtro_listagem, $pa_parametros_campo) { if (isset($pa_filtro_listagem[$va_dependencia["campo"]]) && $pa_filtro_listagem[$va_dependencia["campo"]]) { - $va_filtro[$va_dependencia["atributo"]] = $pa_filtro_listagem[$va_dependencia["campo"]]; + if (in_array($va_dependencia["campo"], $va_filtros_pos_aplicacao)) + continue; + + $va_filtro[$va_dependencia["atributo"]] = $pa_filtro_listagem[$va_dependencia["campo"]]; + + if (isset($va_dependencia["forcar_pos_aplicacao"])) + { + $va_filtros_pos_aplicacao = array_merge($va_filtros_pos_aplicacao, $va_dependencia["forcar_pos_aplicacao"]); + } } else { // Se a dependência "obrigatória" existe e nenhum valor é passado, não gera a lista + if (isset($va_dependencia["obrigatoria"]) && $va_dependencia["obrigatoria"]) return false; } + + if (isset($va_dependencia["relacao_hierarquica"])) + { + $vs_atributo_hierarquico = $va_dependencia["relacao_hierarquica"]; + $vb_aplicar_filtro_banco_dados = false; + } } } @@ -50,6 +80,9 @@ public function preencher($pa_filtro_listagem, $pa_parametros_campo) { foreach ($pa_parametros_campo["filtro"] as $va_filtro_combo) { + if (in_array($va_filtro_combo["atributo"], $va_filtros_pos_aplicacao)) + continue; + if (isset($va_filtro_combo["operador"])) $va_filtro[$va_filtro_combo["atributo"]] = [$va_filtro_combo["valor"], $va_filtro_combo["operador"]]; else @@ -78,20 +111,98 @@ public function preencher($pa_filtro_listagem, $pa_parametros_campo) $vn_primeiro_registro = 0; $vn_numero_maximo_itens = 0; + if (isset($pa_parametros_campo["numero_maximo_itens"])) { $vn_primeiro_registro = 1; $vn_numero_maximo_itens = $pa_parametros_campo["numero_maximo_itens"]; } - //var_dump(get_class($vo_objeto), $va_filtro); +//var_dump(get_class($vo_objeto), $va_filtro); + + $this->objects = $vo_objeto->ler_lista($va_filtro, $vs_visualizacao, $vn_primeiro_registro, $vn_numero_maximo_itens, ($pa_parametros_campo["ordenacao"] ?? null), null, null, 1, false); + + //var_dump($this->objects); + + if (count($va_filtros_pos_aplicacao)) + { + foreach($this->objects as $va_item) + { + $va_items_hierarquia[] = $va_item; + + while (isset($va_item[$vs_atributo_hierarquico])) + { + $va_items_hierarquia[] = $va_item[$vs_atributo_hierarquico]; + + $va_item = $va_item[$vs_atributo_hierarquico]; + } + } - $va_itens = $vo_objeto->ler_lista($va_filtro, $vs_visualizacao, $vn_primeiro_registro, $vn_numero_maximo_itens); + $va_itens_lista = array(); - //var_dump($va_itens); + foreach ($va_items_hierarquia as $va_item) + { + $vb_adicionar_item_lista = false; + $vb_verificou_filtros = false; + + foreach ($va_dependencias as $va_dependencia) + { + if (!in_array($va_dependencia["campo"], $va_filtros_pos_aplicacao)) + continue; + + if (!isset($pa_filtro_listagem[$va_dependencia["campo"]]) && isset($va_dependencia["obrigatoria"]) && $va_dependencia["obrigatoria"]) + { + $vb_verificou_filtros = true; + $vb_adicionar_item_lista = false; + + break; + } + + if (!isset($pa_filtro_listagem[$va_dependencia["campo"]]) && (!isset($va_dependencia["obrigatoria"]) || !$va_dependencia["obrigatoria"])) + continue; + + $vs_atributo = $va_dependencia["atributo_pos_aplicacao"] ?? $va_dependencia["atributo"]; + + if (ler_valor1($vs_atributo, $va_item) == $pa_filtro_listagem[$va_dependencia["campo"]]) + $vb_adicionar_item_lista = true; + else + { + $vb_adicionar_item_lista = false; + } + + $vb_verificou_filtros = true; + + if (!$vb_adicionar_item_lista) break; + } + + if ($vb_verificou_filtros && !$vb_adicionar_item_lista) continue; + + foreach ($pa_parametros_campo["filtro"] as $va_filtro_combo) + { + if (!in_array($pa_parametros_campo["atributo"], $va_filtros_pos_aplicacao)) + continue; + + if ($va_filtro_combo["operador"] == "<=>") + { + if (!isset($va_item[$va_filtro_combo["atributo"]])) + $vb_adicionar_item_lista = true; + } + else + { + if (ler_valor1($va_filtro_combo["atributo_pos_aplicacao"], $va_item) == $va_filtro_combo["valor"]) + $vb_adicionar_item_lista = true; + } + } + + if ($vb_adicionar_item_lista) + $va_itens_lista[] = $va_item; + } + + $this->objects = $va_itens_lista; + } } - foreach($va_itens as $va_item) + foreach($this->objects as $va_item) { if (isset($pa_parametros_campo["atributos"])) { @@ -164,24 +275,27 @@ public function preencher($pa_filtro_listagem, $pa_parametros_campo) $this->adicionar_item($vn_item_lista_option, $vs_item_lista_value); } + if (count($this->itens)) + asort($this->itens); + // Se atributo_inverso está configurado, vamos verificar // se existem relacionamentos não criados entre o filtro // e o objeto que ele filtra //////////////////////////////////////////////////////// - if (isset($pa_parametros_campo["objeto_filtrado"]) && (!isset($pa_filtro_listagem[$pa_parametros_campo["atributo"]])) && count($va_itens)) - { - $vo_objeto_filtrado = new $pa_parametros_campo["objeto_filtrado"](''); + // if (isset($pa_parametros_campo["objeto_filtrado"]) && (!isset($pa_filtro_listagem[$pa_parametros_campo["atributo"]])) && count($this->objects)) + // { + // $vo_objeto_filtrado = new $pa_parametros_campo["objeto_filtrado"](''); - $va_atributos = explode(",", $pa_parametros_campo["atributo"]); + // $va_atributos = explode(",", $pa_parametros_campo["atributo"]); - $pa_filtro_listagem[$va_atributos[0]] = ["0", "_EXISTS_"]; + // $pa_filtro_listagem[$va_atributos[0]] = ["0", "_EXISTS_"]; - $vn_numero_relacionamentos = $vo_objeto_filtrado->ler_numero_registros($pa_filtro_listagem); + // $vn_numero_relacionamentos = $vo_objeto_filtrado->ler_numero_registros($pa_filtro_listagem); - if ($vn_numero_relacionamentos) - $this->adicionar_item("_NO_", "[Sem atribução]"); - } + // if ($vn_numero_relacionamentos) + // $this->adicionar_item("_NO_", "[Sem atribução]"); + // } //////////////////////////////////////////////////////// } @@ -201,20 +315,18 @@ public function build(&$pa_valores_form=null, $pa_parametros_campo=array(), $ps_ $vb_pode_exibir = $this->verificar_exibicao($pa_valores_form, $pa_parametros_campo); - //var_dump($pa_parametros_campo); $this->preencher($pa_valores_form, $pa_parametros_campo); $va_itens_campo = $this->get_itens(); $vs_valor_campo = ""; if (isset($pa_valores_form[$pa_parametros_campo["atributo"]])) { - if (is_array($pa_valores_form[$pa_parametros_campo["atributo"]])) + if (is_array($pa_valores_form[$pa_parametros_campo["atributo"]]) || ($pa_valores_form[$pa_parametros_campo["atributo"]] == 0)) $vs_valor_campo = "_NO_"; else $vs_valor_campo = $pa_valores_form[$pa_parametros_campo["atributo"]]; } - if ($ps_path_campo_filtro != "") { require $ps_path_campo_filtro; diff --git a/src/lib/system/campo_sistema.php b/src/lib/system/campo_sistema.php index bfa9339..3f7b183 100755 --- a/src/lib/system/campo_sistema.php +++ b/src/lib/system/campo_sistema.php @@ -377,7 +377,7 @@ public function inicializar_visualizacoes() ]; } - public function ler_lista($pa_filtros_busca = null, $ps_visualizacao = "lista", $pn_primeiro_registro = 0, $pn_numero_registros = 20, $pa_order_by = null, $ps_order = null, $pa_log_info = null, $pn_idioma_codigo = 1) + public function ler_lista($pa_filtros_busca = null, $ps_visualizacao = "lista", $pn_primeiro_registro = 0, $pn_numero_registros = 20, $pa_order_by = null, $ps_order = null, $pa_log_info = null, $pn_idioma_codigo = 1, $pb_retornar_ramos_inferiores = true) { $va_campos_sistema_pai = array(); diff --git a/src/lib/system/formato_imagem.php b/src/lib/system/formato_imagem.php index 7622084..0fcdd86 100644 --- a/src/lib/system/formato_imagem.php +++ b/src/lib/system/formato_imagem.php @@ -27,7 +27,7 @@ public function ler($pn_codigo, $ps_visualizacao = 'lista', $pn_idioma_codigo = return $va_resultado; } -public function ler_lista($pa_filtros_busca=null, $ps_visualizacao="lista", $pn_primeiro_registro=0, $pn_numero_registros=20, $pa_order_by=null, $ps_order=null, $pa_log_info=null, $pn_idioma_codigo=1) +public function ler_lista($pa_filtros_busca=null, $ps_visualizacao="lista", $pn_primeiro_registro=0, $pn_numero_registros=20, $pa_order_by=null, $ps_order=null, $pa_log_info=null, $pn_idioma_codigo=1, $pb_retornar_ramos_inferiores = true) { $va_itens = array(); $va_resultado = array(); diff --git a/src/lib/system/genero_gramatical.php b/src/lib/system/genero_gramatical.php index b463cc0..b06d0b9 100755 --- a/src/lib/system/genero_gramatical.php +++ b/src/lib/system/genero_gramatical.php @@ -39,7 +39,7 @@ public function ler($pn_codigo, $ps_visualizacao = 'lista', $pn_idioma_codigo = return $va_resultado; } - public function ler_lista($pa_filtros_busca = null, $ps_visualizacao = "lista", $pn_primeiro_registro = 0, $pn_numero_registros = 20, $pa_order_by = null, $ps_order = null, $pa_log_info = null, $pn_idioma_codigo = 1) + public function ler_lista($pa_filtros_busca = null, $ps_visualizacao = "lista", $pn_primeiro_registro = 0, $pn_numero_registros = 20, $pa_order_by = null, $ps_order = null, $pa_log_info = null, $pn_idioma_codigo = 1, $pb_retornar_ramos_inferiores = true) { $va_itens = array(); $va_resultado = array(); diff --git a/src/lib/system/importacao_refatorado.php b/src/lib/system/importacao_refatorado.php new file mode 100644 index 0000000..407b1f9 --- /dev/null +++ b/src/lib/system/importacao_refatorado.php @@ -0,0 +1,582 @@ +id_objeto_importacao = $ps_id_objeto_importacao; + $this->usuario_logado_instituicao_codigo = $pn_usuario_logado_instituicao_codigo; + $this->usuario_logado_codigo = $ps_usuario_codigo; + + if ($this->get_id_objeto_importacao()) { + $this->inicializar_objeto_importacao(); + } + + } + + public function complementar_item_acervo() { + return [ + "texto_publicado_online" => "1", + "texto_publicado_online_chk" => "1", + "item_acervo_acervo_codigo" => "1", + "item_acervo_instituicao_codigo" => 1 + ]; + } + + public function is_item_acervo($pa_id_objeto) { + return is_subclass_of(new $pa_id_objeto, "texto"); + + } + + public function inicializar_timezone_importacao() { + $this->timezone = new DateTimeZone('America/Sao_Paulo'); + } + public function inicializar_data_inicio_importacao() { + $this->inicio = new DateTime('now', $this->timezone); + } + public function get_existencia_registro($po_objeto_busca, $ps_valor_busca_registro, $pb_is_item_acervo) + { + $po_objeto_busca->inicializar_campos_importacao(); + $va_campos_importacao = $po_objeto_busca->get_campos_importacao(); + $va_resultado_busca = array(); + if ($pb_is_item_acervo) + { + $vs_campo_identificador_registro = $va_campos_importacao["identificador_registro"][0]; + $va_parametros_busca_registro[$vs_campo_identificador_registro] = [ + $ps_valor_busca_registro + ]; + $va_resultado_busca = $po_objeto_busca->ler_lista($va_parametros_busca_registro); + } + + return $va_resultado_busca; + } + + public function get_index_identificador_objeto_importacao($pb_is_item_acervo): int|null { + foreach(array_values($this->campos_destino_selecao) as $vn_posicao_campo_destino => $vs_identificacao_campo_destino) { + if (str_contains($vs_identificacao_campo_destino, $pb_is_item_acervo ? "_identificador" : "_nome")) { + return $vn_posicao_campo_destino; + } + } + return null; + } + function get_codigo_objeto_from_nome($ps_id_objeto_busca, $ps_atributo_busca, $ps_valor_busca) + { + $vo_objeto_de_busca = new $ps_id_objeto_busca; + $vs_chave_primaria = $vo_objeto_de_busca->get_chave_primaria()[0]; + $va_parametro_busca[$ps_atributo_busca] = [$ps_valor_busca]; + $va_retorno_busca = $vo_objeto_de_busca->ler_lista($va_parametro_busca); + return $va_retorno_busca[0][$vs_chave_primaria] ?? ""; + } + + public function importar(): array { + + $this->logger = new logger_importacao($this->id_objeto_importacao, $this->modo_importacao, $this->debug, $this->tolerancia_erros); + + $this->objeto_importacao_is_item_acervo = $this->is_item_acervo($this->objeto_importacao); + $vn_index_identificador_objeto_importacao = $this->get_index_identificador_objeto_importacao($this->is_item_acervo($this->objeto_importacao)); + + $this->objeto_importacao->iniciar_transacao(); + foreach ($this->dados_origem as $vn_linha_importacao => $va_dados_linha_importacao) + { + $this->linha_operacao_atual = $vn_linha_importacao; + $this->processar_linha($va_dados_linha_importacao, $vn_index_identificador_objeto_importacao); + } + + $this->objeto_importacao->finalizar_transacao(); + + return $this->logger->finalizar_relatorio(); + + } + public function processar_linha($pa_linha_importacao, $pn_index_identificador_objeto_importacao) { + $va_dados_insercao_linha = array(); + + if (in_array($this->modo_importacao, ["upsert", "update", "create"])) { + + if (isset($pn_index_identificador_objeto_importacao)) { + if (!empty($pa_linha_importacao[$pn_index_identificador_objeto_importacao])) { + $vs_id_registro = $pa_linha_importacao[$pn_index_identificador_objeto_importacao]; + $va_resultado_busca = $this->get_existencia_registro($this->objeto_importacao, $vs_id_registro, $this->objeto_importacao_is_item_acervo); + unset($vs_id_registro); + + if (empty($va_resultado_busca) && in_array($this->modo_importacao, ["update"])) { + $this->logger->adicionar_operacao("Negativo", "Objeto não encontrado em operação de atualização.", "Atualização"); + return; + } + + $va_dados_insercao_linha = array_intersect_key($va_dados_insercao_linha, $va_resultado_busca[0]); + $vs_chave_primaria_objeto_importacao = $this->objeto_importacao->get_chave_primaria()[0]; + $va_dados_insercao_linha[$vs_chave_primaria_objeto_importacao] = $va_resultado_busca[0][$vs_chave_primaria_objeto_importacao]; + + if (!empty($this->objeto_importacao->get_campo_relacionamento_pai)) { + $va_dados_insercao_linha[$this->objeto_importacao->get_campo_relacionamento_pai] = $va_resultado_busca[0][$this->objeto_importacao->get_campo_relacionamento_pai]; + } + + } elseif (in_array($this->modo_importacao, ["update"])) { + // id não fornecido + $this->logger->adicionar_operacao("Negativo", "Objeto sem identificador em operação de atualização.", "Atualização"); + + } + } + + + $this->inicializar_campos_objeto_importacao(); + // Processar colunas + foreach($pa_linha_importacao as $vn_index_coluna_importacao => $vs_dado_coluna_importacao) + { + $this->index_col_operacao_atual = $vn_index_coluna_importacao; + + if (array_key_exists($vn_index_coluna_importacao, $this->campos_destino_selecao)) + { + $vs_chave_campo_destino_atual = $this->campos_destino_selecao[$vn_index_coluna_importacao]; + $va_campo_destino = $this->campos_edicao[$vs_chave_campo_destino_atual]; + $va_campo_config = $this->campos_variantes_importacao[$vn_index_coluna_importacao] ?? []; + + $this->processar_campo( $vs_dado_coluna_importacao, $vs_chave_campo_destino_atual, $va_campo_destino, $va_campo_config, $va_dados_insercao_linha); + } + } + + //TODO: Converter isso em funcao, e considerar tolerancia de erros. chave de código sem atributo presente = falha + + if (!isset($va_dados_insercao_linha["item_acervo_identificador"]) && $this->objeto_importacao_is_item_acervo) + { + $va_dados_insercao_linha["item_acervo_identificador"] = ""; + } + + + $va_dados_insercao_linha["instituicao_codigo"] = $this->usuario_logado_instituicao_codigo; + $va_dados_insercao_linha["usuario_logado_codigo"] = $this->usuario_logado_codigo; + if ($this->objeto_importacao_is_item_acervo) { + $va_dados_insercao_linha = array_merge($va_dados_insercao_linha, $this->complementar_item_acervo()); + + } + + + $this->logger->adicionar_operacao( + "Positivo", + "Objeto manipulado com sucesso. ", + "Main", + $this->objeto_importacao->salvar($va_dados_insercao_linha)); + } + + } + + + public function processar_campo($ps_valor_celula, $ps_chave_campo_destino, $pa_campo_destino, $pa_campo_config, &$pa_dados_insercao_linha): void + { + $vb_text = $pa_campo_destino[0] === "html_text_input"; + $vb_numero = $pa_campo_destino[0] === "html_number_input"; + $vb_data = $pa_campo_destino[0] === "html_date_input"; + $vb_relacionamento = isset($pa_campo_destino["objeto"]) && class_exists($pa_campo_destino["objeto"]); + + if ($vb_text) + { + $pa_dados_insercao_linha[$ps_chave_campo_destino] = $ps_valor_celula; + } + elseif ($vb_numero) + { + if (is_numeric($ps_valor_celula)) + { + $pa_dados_insercao_linha[$ps_chave_campo_destino] = $ps_valor_celula; + } // TODO: else: Tratar erro + } + elseif ($vb_data) + { + $pa_dados_insercao_linha = array_merge($pa_dados_insercao_linha, $this->processar_data($ps_valor_celula, "")); + } + elseif ($vb_relacionamento) + { + $ps_separador_valores = $pa_campo_config["separador_valores"] ?? ""; + $va_valores_celula = empty($ps_separador_valores) ? [$ps_valor_celula] : explode($ps_separador_valores, $ps_valor_celula); + $va_relacionamentos = []; + $va_valores_celula = array_map('trim', $va_valores_celula); + + foreach ($va_valores_celula as $vs_valor_celula) + { + if (empty($vs_valor_celula)) + { + continue; + } + + $va_relacionamento = $this->processar_relacionamento($ps_chave_campo_destino, $pa_campo_destino, $vs_valor_celula); + $va_keys_comuns = array_intersect_key($va_relacionamento, $va_relacionamentos); + foreach ($va_keys_comuns as $vs_key_comum => $vs_valor_comum) + { + $vs_novo_valor = $va_relacionamento[$vs_key_comum]; + $va_relacionamentos[$vs_key_comum] = $va_relacionamentos[$vs_key_comum] . "|" . $vs_novo_valor; + unset($va_relacionamento[$vs_key_comum]); + } + + $va_relacionamentos = array_merge($va_relacionamentos, $va_relacionamento); + } + + $pa_dados_insercao_linha = array_merge($pa_dados_insercao_linha, $va_relacionamentos); + } + } + + + public function processar_relacionamento($ps_chave_campo_destino, $pa_campo_destino, $ps_dado_campo_destino) + { + if (empty($ps_dado_campo_destino)) + { + return []; + } + + $va_relacionamento = array(); + $vs_objeto_relacionamento = $pa_campo_destino["objeto"]; + $vb_entidade = $vs_objeto_relacionamento === "entidade"; // TODO: Hardcodado por enquanto + $vs_tipo = ""; + + if ($vb_entidade) + { + // Tipo de entidade em parênteses: Joe Doe (editor) + $vs_regex_entidade = "/\((.*?)\)/"; + preg_match($vs_regex_entidade, $ps_dado_campo_destino, $va_matches_entidade); + $vs_tipo = $va_matches_entidade[1] ?? ""; + $vs_replace = $va_matches_entidade[0] ?? ""; + $ps_dado_campo_destino = str_replace($vs_replace, "", $ps_dado_campo_destino); + $ps_dado_campo_destino = trim($ps_dado_campo_destino); + } + + $vs_obj_relacionamento_atributo_busca = $pa_campo_destino["procurar_por"] ?? $pa_campo_destino["atributos"][1]; + $vn_codigo_objeto_relacionamento = $this->get_codigo_objeto_from_nome( + $vs_objeto_relacionamento, + $vs_obj_relacionamento_atributo_busca, + $ps_dado_campo_destino + ); + + if (empty($vn_codigo_objeto_relacionamento)) + { + $vo_item_relacionado = new $vs_objeto_relacionamento; + $vo_item_relacionado->inicializar_campos_edicao(); + $va_insercao_item_relacionado = array_fill_keys(array_keys($vo_item_relacionado->get_campos_edicao()), ""); + $vs_campo_salvar = $pa_campo_destino["campo_salvar"] ?? $vs_obj_relacionamento_atributo_busca; + $va_insercao_item_relacionado[$vs_campo_salvar] = $ps_dado_campo_destino; + $va_insercao_item_relacionado["instituicao_codigo"] = $this->usuario_logado_instituicao_codigo; + $va_insercao_item_relacionado["usuario_logado_codigo"] = $this->usuario_logado_codigo; + $vn_codigo_objeto_relacionamento = $vo_item_relacionado->salvar($va_insercao_item_relacionado); + } + + if (empty($vn_codigo_objeto_relacionamento)) + { + // TODO: Tratar erro + return []; + } + + $va_relacionamento[$ps_chave_campo_destino] = $vn_codigo_objeto_relacionamento; + + if ($this->get_campo_tem_subcampo($pa_campo_destino)) + { + $va_subcampos = $pa_campo_destino["subcampos"]; + $vb_added = false; + + // TODO: Considerar separadores de valores e subcampos + foreach ($va_subcampos as $vs_chave_subcampo => $va_subcampo) + { + $vs_valor_padrao = $va_subcampo["valor_padrao"] ?? ""; + $vs_composite_key = $vs_chave_subcampo . "_" . $vn_codigo_objeto_relacionamento; + + if (isset($va_subcampo["objeto"]) && !empty($vs_tipo) && !$vb_added) + { + $vn_sub_campo_codigo = $this->processar_relacionamento($vs_chave_subcampo, $va_subcampo, $vs_tipo); + $vb_added = true; + if ($vn_sub_campo_codigo) + { + $va_relacionamento[$vs_composite_key] = $vn_sub_campo_codigo[$vs_chave_subcampo]; + } + } + elseif (!empty($vs_valor_padrao)) + { + $va_relacionamento[$vs_composite_key] = $vs_valor_padrao; + } + } + } + + return $va_relacionamento; + } + + function processar_data($ps_value, $ps_id) + { + + $ps_id = "texto_data"; + + $vo_periodo = new Periodo(); + if (count(explode("-", $ps_value)) >= 3) + { + $ps_value = str_replace("-", "/", $ps_value); + } + + $vo_periodo->tratar_string($ps_value); + + if ($vo_periodo->validar()) + { + + return + [$ps_id => "_data_", + $ps_id . "_sem_data" => $vo_periodo->get_sem_data(), + $ps_id . "_presumido" => $vo_periodo->get_presumido(), + $ps_id . "_dia_inicial" => $vo_periodo->get_dia_inicial(), + $ps_id . "_mes_inicial" => $vo_periodo->get_mes_inicial(), + $ps_id . "_ano_inicial" => $vo_periodo->get_ano_inicial(), + $ps_id . "_dia_final" => $vo_periodo->get_dia_final(), + $ps_id . "_mes_final" => $vo_periodo->get_mes_final(), + $ps_id . "_ano_final" => $vo_periodo->get_ano_final()]; + } + else + { + // TODO: Tratar erro + //$this->add_error("Valor não é uma data válida: " . $ps_value); + } + } + public function get_campo_tem_relacionamento($ps_chave_campo_destino): bool + { + return array_key_exists($ps_chave_campo_destino, $this->campos_relacionamento); + + } + + public function campo_is_lista_controlada($pa_campo) { + return $this->is_item_acervo($pa_campo["objeto"]); + + } + + function get_campo_tem_subcampo($pa_campo) + { + return (isset($pa_campo["subcampos"])); + + } + + public function inicializar_objeto_importacao() { + $this->objeto_importacao = new $this->id_objeto_importacao; + $this->objeto_importacao_chave_primaria = $this->objeto_importacao->get_chave_primaria(); + + } + public function inicializar_campos_edicao_objeto_importacao() { + if ($this->objeto_importacao) { + $this->campos_edicao = $this->objeto_importacao->inicializar_campos_edicao(); + return true; + } + return false; + } + + public function inicializar_campos_objeto_importacao() { + if ($this->objeto_importacao) { + // separados pois não dá pra criar objeto por retorno de funcao em runtime + $vs_id_objeto_pai = $this->objeto_importacao->get_objeto_pai(); + $vo_objeto_pai = new $vs_id_objeto_pai; + + $this->objeto_importacao->inicializar_campos_importacao(); + $this->campos_importacao = $this->objeto_importacao->get_campos_importacao(); + $this->campos_relacionamento = array_merge($this->objeto_importacao->inicializar_relacionamentos(), $vo_objeto_pai->inicializar_relacionamentos()); + return true; + } + return false; + } + public function inicializar_variantes_campos_importacao($pa_valores_padrao, $pa_criar_itens_relacionados, $pa_separadores_valores, $pa_separadores_subcampo): void { + foreach (array_keys($this->campos_destino_selecao) as $vn_posicao_campo_destino) { + $this->campos_variantes_importacao[$vn_posicao_campo_destino] = [ + "valor_padrao" => $pa_valores_padrao[$vn_posicao_campo_destino], + "separador_subcampos" => $pa_separadores_subcampo[$vn_posicao_campo_destino] ?? false, + "separador_valores" => $pa_separadores_valores[$vn_posicao_campo_destino], + "criar_itens_relacionados" => isset($pa_criar_itens_relacionados[$vn_posicao_campo_destino]) + // [tipo de relacao padrao] + + ]; + } + } + public function get_operacoes(): array + { + return $this->operacoes; + } + + public function get_modo_importacao(): string + { + return $this->modo_importacao; + } + + public function get_debug(): bool + { + return $this->debug; + } + + public function get_tolerancia_erros(): bool + { + return $this->tolerancia_erros; + } + + public function get_separador_hierarquia(): string + { + return $this->separador_hierarquia; + } + + public function get_id_objeto_importacao(): string + { + return $this->id_objeto_importacao; + } + + public function get_objeto_importacao(): object + { + return $this->objeto_importacao; + } + + public function get_campos_edicao(): array + { + return $this->campos_edicao; + } + public function get_campo_edicao($ps_label): array + { + return array_key_exists($ps_label, $this->campos_edicao) ? $this->campos_edicao[$ps_label] : []; + + } + public function get_campos_relacionamento_objeto_importacao(): array + { + return $this->objeto_importacao->campos_relacionamento; + } + + public function get_campos_origem_label(): array + { + return $this->campos_origem_label; + } + public function get_campo_origem_label($pn_index_selecao): string { + return $pn_index_selecao <= count($this->campos_origem_label) ? $this->campos_origem_label[$pn_index_selecao] : ""; + } + public function get_campos_destino_selecao(): array + { + return $this->campos_destino_selecao; + } + public function get_campo_destino_selecao($pn_index_selecao): string { + return $this->campos_destino_selecao[$pn_index_selecao]; + + } + public function get_dados_origem(): array + { + return $this->dados_origem; + } + public function get_caminho_arquivo_importacao(): string + { + if (!isset($this->caminho_arquivo_importacao)) + { + $this->caminho_arquivo_importacao = $_POST["caminho_arquivo_importacao"] ?? ""; + } + + return $this->caminho_arquivo_importacao; + } + public function set_dados_origem($dados_origem): void + { + $this->dados_origem = $dados_origem; + } + + public function set_campos_destino_selecao($pa_campos_destino_selecao): void + { + $this->campos_destino_selecao = array_filter($pa_campos_destino_selecao, function($vs_campo) { + return !empty($vs_campo); + }); + } + + public function set_campos_origem_label($campos_origem_label): void + { + $this->campos_origem_label = $campos_origem_label; + } + + public function set_campos_relacionamento($campos_relacionamento): void + { + $this->campos_relacionamento = $campos_relacionamento; + } + + public function set_campos_edicao($campos_edicao): void + { + $this->campos_edicao = $campos_edicao; + } + + public function set_objeto_importacao($objeto_importacao): void + { + $this->objeto_importacao = $objeto_importacao; + } + + public function set_id_objeto_importacao(mixed $id_objeto_importacao): void + { + $this->id_objeto_importacao = $id_objeto_importacao; + } + + public function set_separador_hierarquia($separador_hierarquia): void + { + $this->separador_hierarquia = $separador_hierarquia; + } + + public function set_tolerancia_erros($tolerancia_erros): void + { + $this->tolerancia_erros = $tolerancia_erros; + } + + public function set_debug($debug): void + { + $this->debug = $debug; + } + + public function set_modo_importacao($modo_importacao): void + { + $this->modo_importacao = $modo_importacao; + } + + public function set_operacoes($operacoes): void + { + $this->operacoes = $operacoes; + } + + public function set_caminho_arquivo_importacao($caminho_arquivo_importacao): void + { + $this->caminho_arquivo_importacao = $caminho_arquivo_importacao; + } + + public function set_parametros_importacao($pa_parametros_importacao): void + { + $this->modo_importacao = $pa_parametros_importacao["import_mode"] ?? "create"; + $this->debug = $pa_parametros_importacao["import_debug"] ?? false; + $this->tolerancia_erros = $pa_parametros_importacao["import_allow_errors"] ?? false; + $this->separador_hierarquia = $pa_parametros_importacao["import_separator_hierarchy"] ?? ">"; + } +} diff --git a/src/lib/system/logger_importacao.php b/src/lib/system/logger_importacao.php new file mode 100644 index 0000000..142dcc0 --- /dev/null +++ b/src/lib/system/logger_importacao.php @@ -0,0 +1,58 @@ +timezone = new DateTimeZone('America/Sao_Paulo'); + $this->inicio = new DateTime('now', $this->timezone); + $this->id_objeto_importacao = $ps_id_objeto_importacao; + $this->modo_importacao = $ps_modo_importacao; + $this->debug = $pb_debug; + $this->tolerancia_erros = $pb_tolerancia_erros; + $this->operacoes = array(); + + } + + public function adicionar_operacao($ps_resultado, $ps_mensagem, $ps_tipo_operacao, $ps_codigo_registro = null): void + { + $this->operacoes[] = [ + "resultado" => $ps_resultado, "mensagens" => [$ps_mensagem], "tipo_operacao" => $ps_tipo_operacao, "codigo_registro" => $ps_codigo_registro + ]; + } + + public function complementar_operacao_atual($ps_mensagem): void + { + $this->operacoes[array_key_last($this->operacoes)]["mensagens"][] = $ps_mensagem; + } + + public function finalizar_relatorio(): array + { + $this->fim = new DateTime('now', $this->timezone); + $this->duracao = $this->fim->diff($this->inicio); + + return [ + "objeto_importado" => $this->id_objeto_importacao, + "operacoes" => $this->operacoes, + "modo_import" => $this->modo_importacao, + "duracao" => $this->duracao->format('%i minutos, %s segundos'), + "debug" => $this->debug, + "tolerancia_erros" => $this->tolerancia_erros, + + ]; + } + +} +?> + + diff --git a/src/lib/system/modelo_etiqueta.php b/src/lib/system/modelo_etiqueta.php index 3565b9f..5769c92 100644 --- a/src/lib/system/modelo_etiqueta.php +++ b/src/lib/system/modelo_etiqueta.php @@ -24,7 +24,7 @@ public function ler($pn_codigo, $ps_visualizacao = 'lista', $pn_idioma_codigo = return $va_resultado; } - public function ler_lista($pa_filtros_busca = null, $ps_visualizacao = "lista", $pn_primeiro_registro = 0, $pn_numero_registros = 0, $pa_order_by = null, $ps_order = null, $pa_log_info = null, $pn_idioma_codigo = 1) + public function ler_lista($pa_filtros_busca = null, $ps_visualizacao = "lista", $pn_primeiro_registro = 0, $pn_numero_registros = 0, $pa_order_by = null, $ps_order = null, $pa_log_info = null, $pn_idioma_codigo = 1, $pb_retornar_ramos_inferiores = true) { $va_itens = array(); $va_resultado = array(); diff --git a/src/lib/system/objeto_base.php b/src/lib/system/objeto_base.php old mode 100644 new mode 100755 index f9894f8..c66dfc0 --- a/src/lib/system/objeto_base.php +++ b/src/lib/system/objeto_base.php @@ -45,6 +45,7 @@ class objeto_base protected $va_order_by; public $controlador_acesso = array(); + public $registros_protegidos = array(); // Eu posso criar um objeto que vai armazenar informações // de vários tipos de objetos @@ -645,7 +646,7 @@ private function tratar_filtros_busca($pa_filtros_busca) return $va_filtros_busca_union; } - public function ler_numero_registros($pa_filtros_busca = null, $pa_log_info = null) + public function ler_numero_registros($pa_filtros_busca = null, $pa_log_info = null, $pb_retornar_ramos_inferiores = true) { // Vamos tratar aqui o caso específico de o filtro de busca incluir mais de um campo //////////////////////////////////////////////////////////////////////////////////// @@ -672,7 +673,8 @@ public function ler_numero_registros($pa_filtros_busca = null, $pa_log_info = nu $vn_numero_registros = 0; $vo_banco = $this->get_banco(); - foreach ($va_objetos as $vs_objeto) { + foreach ($va_objetos as $vs_objeto) + { $contador = 0; $va_resultados_objeto = array(); @@ -687,6 +689,8 @@ public function ler_numero_registros($pa_filtros_busca = null, $pa_log_info = nu $va_joins_select = array(); $va_wheres_select = array(); + $va_tabelas_adicionadas = array(); + if ($vs_objeto) $vo_objeto = new $vs_objeto($vs_objeto); @@ -699,6 +703,8 @@ public function ler_numero_registros($pa_filtros_busca = null, $pa_log_info = nu } } + $va_tabelas_adicionadas[$vo_objeto->tabela_banco][] = $vo_objeto->tabela_banco; + $va_campos_select[] = " DISTINCT " . $vo_objeto->tabela_banco . ".Codigo as " . $vo_objeto->tabela_banco . "_codigo"; // Se algum atributo do objeto tiver um valor padrão, tem que filtrar por ele @@ -715,7 +721,7 @@ public function ler_numero_registros($pa_filtros_busca = null, $pa_log_info = nu } } - $this->montar_filtros_busca($va_filtros_busca, $vo_objeto, $va_joins_select, $va_wheres_select, $va_tipos_parametros_select, $va_parametros_select); + $this->montar_filtros_busca($va_filtros_busca, $vo_objeto, $va_joins_select, $va_wheres_select, $va_tipos_parametros_select, $va_parametros_select, $va_tabelas_adicionadas, $pb_retornar_ramos_inferiores); $this->montar_parametros_log($pa_log_info, $vo_objeto, $va_joins_select, $va_wheres_select, $va_tipos_parametros_select, $va_parametros_select); @@ -753,7 +759,7 @@ public function ler_numero_registros($pa_filtros_busca = null, $pa_log_info = nu public function ler($pn_codigo, $ps_visualizacao = 'lista', $pn_idioma_codigo = 1) { - $va_resultado = $this->ler_lista([$this->chave_primaria[0] => $pn_codigo], $ps_visualizacao, 0, 1, null, null, null, $pn_idioma_codigo); + $va_resultado = $this->ler_lista([$this->chave_primaria[0] => $pn_codigo], $ps_visualizacao, 0, 1, null, null, null, $pn_idioma_codigo, false); if (count($va_resultado)) { $va_resultado = $va_resultado[0]; @@ -816,7 +822,7 @@ private function montar_valores_busca($pa_parametro, &$pa_valores_busca = array( foreach ($va_valores_filtro as $vs_valor_filtro) { - if (trim($vs_valor_filtro) != "") + if (trim($vs_valor_filtro ?? "") != "") { $vb_tem_valor = true; $va_interrogracoes[] = "?"; @@ -882,7 +888,7 @@ private function montar_valores_busca($pa_parametro, &$pa_valores_busca = array( return $vb_tem_valor; } - private function montar_filtros_busca($pa_filtros_busca, $po_objeto, &$pa_joins_select = array(), &$pa_wheres_select = array(), &$pa_tipos_parametros_select = array(), &$pa_parametros_select = array(), &$pa_tabelas_adicionadas = array()) + private function montar_filtros_busca($pa_filtros_busca, $po_objeto, &$pa_joins_select = array(), &$pa_wheres_select = array(), &$pa_tipos_parametros_select = array(), &$pa_parametros_select = array(), &$pa_tabelas_adicionadas = array(), $pb_retornar_ramos_inferiores = true, &$pa_joins_trail = array()) { if (isset($pa_filtros_busca)) { @@ -891,6 +897,8 @@ private function montar_filtros_busca($pa_filtros_busca, $po_objeto, &$pa_joins_ foreach ($pa_filtros_busca as $vs_parametro_nome => $va_parametro) { + $pa_joins_trail["current_trail"] = $pa_tabelas_adicionadas[0] ?? ""; + // Tentativa: restringir pela existência de um relacionamento (hardcoded) ///////////////////////////////////////////////////////////////////////// @@ -1042,7 +1050,7 @@ private function montar_filtros_busca($pa_filtros_busca, $po_objeto, &$pa_joins_ // O terceiro parâmetro vazio quer dizer que ainda não foi feito nenhum join para este filtro ///////////////////////////////////////////////////////////////////////////////////////////// - $this->montar_filtro_busca($va_filtro, $po_objeto, '', $va_valores_busca, $vs_operador, $vs_interrogacoes, $pa_joins_select, $pa_wheres_select, $pa_tipos_parametros_select, $pa_parametros_select, $pa_tabelas_adicionadas, $vs_operador_logico); + $this->montar_filtro_busca($va_filtro, $po_objeto, '', $va_valores_busca, $vs_operador, $vs_interrogacoes, $pa_joins_select, $pa_wheres_select, $pa_tipos_parametros_select, $pa_parametros_select, $pa_tabelas_adicionadas, $vs_operador_logico, $pb_retornar_ramos_inferiores, $pa_joins_trail); } } } @@ -1050,7 +1058,7 @@ private function montar_filtros_busca($pa_filtros_busca, $po_objeto, &$pa_joins_ } } - private function montar_filtro_busca($pa_filtro, $po_objeto, $ps_ultima_tabela_filtro, $pa_valores_busca, $ps_operador, $ps_interrogacoes, &$pa_joins_select = array(), &$pa_wheres_select = array(), &$pa_tipos_parametros_select = array(), &$pa_parametros_select = array(), &$pa_tabelas_adicionadas = array(), $ps_operador_logico = 'AND') + private function montar_filtro_busca($pa_filtro, $po_objeto, $ps_ultima_tabela_filtro, $pa_valores_busca, $ps_operador, $ps_interrogacoes, &$pa_joins_select = array(), &$pa_wheres_select = array(), &$pa_tipos_parametros_select = array(), &$pa_parametros_select = array(), &$pa_tabelas_adicionadas = array(), $ps_operador_logico = 'AND', $pb_retornar_ramos_inferiores = true, &$pa_joins_trail = array()) { // A partir daqui, vamos procurar o campo/atributo ao qual o filtro se refere //////////////////////////////////////////////////////////////////////////// @@ -1091,7 +1099,7 @@ private function montar_filtro_busca($pa_filtro, $po_objeto, $ps_ultima_tabela_f $vo_objeto_pai = new $po_objeto->objeto_pai($po_objeto->objeto_pai); - $this->montar_filtro_busca($va_novo_filtro, $vo_objeto_pai, $ps_ultima_tabela_filtro, $pa_valores_busca, $ps_operador, $ps_interrogacoes, $pa_joins_select, $pa_wheres_select, $pa_tipos_parametros_select, $pa_parametros_select, $pa_tabelas_adicionadas, $ps_operador_logico); + $this->montar_filtro_busca($va_novo_filtro, $vo_objeto_pai, $ps_ultima_tabela_filtro, $pa_valores_busca, $ps_operador, $ps_interrogacoes, $pa_joins_select, $pa_wheres_select, $pa_tipos_parametros_select, $pa_parametros_select, $pa_tabelas_adicionadas, $ps_operador_logico, $pb_retornar_ramos_inferiores, $pa_joins_trail); } elseif (isset($po_objeto->atributos[$va_filtro[0]]) || isset($po_objeto->chave_primaria[$va_filtro[0]])) { @@ -1324,24 +1332,39 @@ private function montar_filtro_busca($pa_filtro, $po_objeto, $ps_ultima_tabela_f } $vs_tabela_filtro = $ps_ultima_tabela_filtro; + if (!$vs_tabela_filtro) $vs_tabela_filtro = $po_objeto->tabela_banco; - if (isset($pa_tabelas_adicionadas[$vs_tabela_join])) + $vs_current_trail = $pa_joins_trail["current_trail"]; + + if ($vs_current_trail) + $vs_new_trail_candidate = $vs_current_trail . ":" . $vs_tabela_join; + else + $vs_new_trail_candidate = $vs_tabela_filtro . ":" . $vs_tabela_join; + + if (isset($pa_joins_trail[$vs_new_trail_candidate])) { - //if ($ps_ultima_tabela_filtro != "") - $vs_alias_tabela_join = $vs_tabela_join . "_" . (count($pa_tabelas_adicionadas[$vs_tabela_join]) + 1); - //else - //$vs_alias_tabela_join = $vs_tabela_join; + $vs_alias_tabela_join = $pa_joins_trail[$vs_new_trail_candidate]; } else - $vs_alias_tabela_join = $vs_tabela_join . "_1"; + { + if (isset($pa_tabelas_adicionadas[$vs_tabela_join])) + $vs_alias_tabela_join = $vs_tabela_join . "_" . (count($pa_tabelas_adicionadas[$vs_tabela_join]) + 1); + else + $vs_alias_tabela_join = $vs_tabela_join . "_1"; + + $pa_joins_trail[$vs_new_trail_candidate] = $vs_alias_tabela_join; + } + + $pa_joins_trail["current_trail"] = $vs_new_trail_candidate; $vs_ultima_tabela_filtro = $vs_alias_tabela_join; if (!in_array($vs_alias_tabela_join, $pa_joins_select)) { $pa_joins_select[$vs_alias_tabela_join] = " JOIN " . $vs_tabela_join . " as " . $vs_alias_tabela_join . " ON " . $vs_tabela_filtro . "." . $vs_campo_chave_importada . " = " . $vs_alias_tabela_join . "." . $vs_campo_tabela_join; + $pa_tabelas_adicionadas[$vs_tabela_join][] = $vs_alias_tabela_join; } @@ -1397,7 +1420,7 @@ private function montar_filtro_busca($pa_filtro, $po_objeto, $ps_ultima_tabela_f } } - $this->montar_filtro_busca($va_novo_filtro, $vo_objeto_relacionamento, $vs_ultima_tabela_filtro, $pa_valores_busca, $ps_operador, $ps_interrogacoes, $pa_joins_select, $pa_wheres_select, $pa_tipos_parametros_select, $pa_parametros_select, $pa_tabelas_adicionadas, $ps_operador_logico); + $this->montar_filtro_busca($va_novo_filtro, $vo_objeto_relacionamento, $vs_ultima_tabela_filtro, $pa_valores_busca, $ps_operador, $ps_interrogacoes, $pa_joins_select, $pa_wheres_select, $pa_tipos_parametros_select, $pa_parametros_select, $pa_tabelas_adicionadas, $ps_operador_logico, $pb_retornar_ramos_inferiores, $pa_joins_trail); } } else { // Se o filtro for chave primária ou atributo da tabela do objeto, a montagem é simples @@ -1418,7 +1441,8 @@ private function montar_filtro_busca($pa_filtro, $po_objeto, $ps_ultima_tabela_f } } - if ($po_objeto->chave_primaria[0] == $va_filtro[0]) { + if ($po_objeto->chave_primaria[0] == $va_filtro[0]) + { $vs_tabela_banco = $po_objeto->tabela_banco; if ($ps_ultima_tabela_filtro) @@ -1507,7 +1531,8 @@ private function montar_filtro_busca($pa_filtro, $po_objeto, $ps_ultima_tabela_f else $pa_wheres_select[] = $vs_tabela_banco . "." . $vs_campo_tabela . " IS NOT NULL "; } - elseif (($pb_retornar_ramos_inferiores = true) && $vo_objeto_coluna->campo_hierarquico && ($va_filtro[0] != $po_objeto->campo_hierarquico)) + //elseif (($pb_retornar_ramos_inferiores) && $vo_objeto_coluna->campo_hierarquico && ($va_filtro[0] != $po_objeto->campo_hierarquico)) + elseif (($pb_retornar_ramos_inferiores) && $vo_objeto_coluna->campo_hierarquico && !is_null($pa_valores_busca[0])) { $this->adicionar_ramos_hierarquicos($po_objeto, $vo_objeto_coluna, $vs_campo_tabela, $vs_tipo_dado_campo, $pa_valores_busca, $ps_operador, $ps_interrogacoes, $ps_operador_logico); } @@ -1551,7 +1576,7 @@ private function montar_filtro_busca($pa_filtro, $po_objeto, $ps_ultima_tabela_f $pa_wheres_select[] = $vs_alias_tabela_join . "." . $vs_campo_tabela_join . " IS NULL "; } } - elseif (($pb_retornar_ramos_inferiores = true) && isset($vo_objeto_tabela_intermediaria) && $vo_objeto_tabela_intermediaria->campo_hierarquico) + elseif (($pb_retornar_ramos_inferiores) && isset($vo_objeto_tabela_intermediaria) && $vo_objeto_tabela_intermediaria->campo_hierarquico) { $vs_campo = "codigo"; $vs_tipo_campo = "i"; @@ -1857,7 +1882,7 @@ private function montar_parametros_fluxos($pa_filtros, $po_objeto, &$pa_joins_se } } - public function ler_lista($pa_filtros_busca = null, $ps_visualizacao = "lista", $pn_primeiro_registro = 0, $pn_numero_registros = 0, $pa_order_by = null, $ps_order = null, $pa_log_info = null, $pn_idioma_codigo = 1) + public function ler_lista($pa_filtros_busca = null, $ps_visualizacao = "lista", $pn_primeiro_registro = 0, $pn_numero_registros = 0, $pa_order_by = null, $ps_order = null, $pa_log_info = null, $pn_idioma_codigo = 1, $pb_retornar_ramos_inferiores = true) { // Vamos tratar aqui o caso específico de o filtro de busca incluir mais de um campo //////////////////////////////////////////////////////////////////////////////////// @@ -1936,11 +1961,13 @@ public function ler_lista($pa_filtros_busca = null, $ps_visualizacao = "lista", $va_tabelas_adicionadas = array(); $va_tabelas_adicionadas[$vs_tabela_banco][] = $vs_tabela_banco; + $va_joins_trail = [$vs_tabela_banco => $vs_tabela_banco]; + // Adiciono um campo na mão para identificar a qual objeto o registro pertence $va_campos_select["_objeto"] = "'" . $vs_objeto . "' as _objeto"; $vb_achou_campo_relacionamento_pai = false; - + foreach ($va_visualizacao as $ps_key_campo_visualizacao => $va_campo_visualizacao) { $vb_achou_campo = false; @@ -2007,12 +2034,16 @@ public function ler_lista($pa_filtros_busca = null, $ps_visualizacao = "lista", if (!$vb_achou_campo) $va_campos_select[$ps_key_campo_visualizacao] = "NULL as " . $ps_key_campo_visualizacao; - if (!$vb_achou_campo) { + if (!$vb_achou_campo) + { $va_campo = explode(".", $va_campo_visualizacao["nome"]); - if (count($va_campo) > 1) { - if (isset($va_atributos_objeto[$va_campo[0]])) { - if (isset($va_atributos_objeto[$va_campo[0]]["objeto"])) { + if (count($va_campo) > 1) + { + if (isset($va_atributos_objeto[$va_campo[0]])) + { + if (isset($va_atributos_objeto[$va_campo[0]]["objeto"])) + { $vs_id_objeto = $va_atributos_objeto[$va_campo[0]]["objeto"]; $vo_objeto_relacionamento = new $vs_id_objeto($vs_id_objeto); @@ -2021,7 +2052,8 @@ public function ler_lista($pa_filtros_busca = null, $ps_visualizacao = "lista", $va_atributos_objeto_relacionamento = $vo_objeto_relacionamento->get_atributos(); - if (isset($va_atributos_objeto_relacionamento[$va_campo[1]])) { + if (isset($va_atributos_objeto_relacionamento[$va_campo[1]])) + { if (!in_array($vs_tabela_join, $va_joins_select)) $va_joins_select[$vs_tabela_join] = " JOIN " . $vs_tabela_join . " ON " . $vs_tabela_banco . "." . $va_atributos_objeto[$va_campo[0]]["coluna_tabela"] . " = " . $vs_tabela_join . "." . $vs_campo_tabela_join; @@ -2043,7 +2075,8 @@ public function ler_lista($pa_filtros_busca = null, $ps_visualizacao = "lista", // Precisamos adicionar o campo de relacionamento do pai, // mesmo se ele não vier na visualização - if ($this->campo_relacionamento_pai && !$vb_achou_campo_relacionamento_pai) { + if ($this->campo_relacionamento_pai && !$vb_achou_campo_relacionamento_pai) + { $va_campos_select[$this->campo_relacionamento_pai] = $vs_tabela_banco . "." . $va_atributos_objeto[$this->campo_relacionamento_pai]["coluna_tabela"]; $vb_achou_campo_relacionamento_pai = true; $vb_achou_campo = true; @@ -2062,20 +2095,20 @@ public function ler_lista($pa_filtros_busca = null, $ps_visualizacao = "lista", foreach ($va_atributos_objeto as $va_atributo_objeto) { - if (isset($va_atributo_objeto["valor_padrao"]) && !in_array(reset($va_atributo_objeto), $va_filtros_busca)) + if (isset($va_atributo_objeto["valor_padrao"]) && !in_array(reset($va_atributo_objeto), $va_filtros_busca ?? [])) { $va_filtros_busca[reset($va_atributo_objeto)] = $va_atributo_objeto["valor_padrao"]; } } - $this->montar_filtros_busca($va_filtros_busca, $vo_objeto, $va_joins_select, $va_wheres_select, $va_tipos_parametros_select, $va_parametros_select, $va_tabelas_adicionadas); + $this->montar_filtros_busca($va_filtros_busca, $vo_objeto, $va_joins_select, $va_wheres_select, $va_tipos_parametros_select, $va_parametros_select, $va_tabelas_adicionadas, $pb_retornar_ramos_inferiores, $va_joins_trail); $this->montar_parametros_log($pa_log_info, $vo_objeto, $va_joins_select, $va_wheres_select, $va_tipos_parametros_select, $va_parametros_select); $this->montar_parametros_fluxos($va_filtros_busca, $vo_objeto, $va_joins_select, $va_wheres_select, $va_tipos_parametros_select, $va_parametros_select); $va_order_by = $this->montar_ordenacao($vo_objeto, $pa_order_by, $va_campos_select, $va_joins_select, $ps_order, $va_tabelas_adicionadas); - + $va_selects[] = [ "tabela" => $vo_objeto->tabela_banco, "campos" => $va_campos_select, @@ -2492,7 +2525,7 @@ public function ler_lista_quantitativa($ps_id_relacionamento, $ps_label_objeto_r $va_filtros_busca[reset($va_atributo_objeto)] = $va_atributo_objeto["valor_padrao"]; } - $this->montar_filtros_busca($va_filtros_busca, $this, $va_joins_select, $va_wheres_select, $va_tipos_parametros_select, $va_parametros_select, $va_tabelas_adicionadas); + $this->montar_filtros_busca($va_filtros_busca, $this, $va_joins_select, $va_wheres_select, $va_tipos_parametros_select, $va_parametros_select, $va_tabelas_adicionadas, $pb_retornar_ramos_inferiores); $va_group_by[] = $ps_label_objeto_relacionamento; $va_group_by[] = "Q_codigo"; @@ -5141,8 +5174,10 @@ public function listar_relacionamentos($pn_codigo, $pb_excluir_objeto = true) $vb_registro_filho = false; $vb_pode_excluir = true; - if (count($this->registros_filhos) && isset($va_relacionamento['objeto'])) { - if (in_array($va_relacionamento['objeto'], array_keys($this->registros_filhos))) { + if (count($this->registros_filhos) && isset($va_relacionamento['objeto'])) + { + if (in_array($va_relacionamento['objeto'], array_keys($this->registros_filhos))) + { $vb_registro_filho = true; if (isset($this->registros_filhos[$va_relacionamento['objeto']]["pode_excluir_pai"]) && !$this->registros_filhos[$va_relacionamento['objeto']]["pode_excluir_pai"] && $pb_excluir_objeto) @@ -6081,6 +6116,8 @@ public function validar_acesso_registro($pn_objeto_codigo, $pa_parametros_acesso { if (isset($pa_parametros_acesso[$vs_parametro_controlador])) { + if ($pa_parametros_acesso[$vs_parametro_controlador] == "_ALL_") continue; + if ($vs_parametro_controlador == $this->get_chave_primaria()[0]) { if (!in_array($pn_objeto_codigo, explode("|", $pa_parametros_acesso[$vs_parametro_controlador]))) @@ -6126,6 +6163,8 @@ public function validar_edicao_registro($pa_valores, $pa_parametros_acesso) { if (isset($pa_parametros_acesso[$vs_parametro_controlador]) && trim($pa_parametros_acesso[$vs_key_controlador]) != "") { + if ($pa_parametros_acesso[$vs_parametro_controlador] == "_ALL_") continue; + $va_atributo_controlador = explode("_0_", $vs_atributo_controlador); if (count($va_atributo_controlador) > 1) diff --git a/src/lib/system/selecao.php b/src/lib/system/selecao.php index 6c3edf7..4313ba6 100755 --- a/src/lib/system/selecao.php +++ b/src/lib/system/selecao.php @@ -277,7 +277,7 @@ public function inicializar_visualizacoes() ]; } - public function ler_lista($pa_filtros_busca = null, $ps_visualizacao = "lista", $pn_primeiro_registro = 0, $pn_numero_registros = 0, $pa_order_by = null, $ps_order = null, $pa_log_info = null, $pn_idioma_codigo = 1) + public function ler_lista($pa_filtros_busca = null, $ps_visualizacao = "lista", $pn_primeiro_registro = 0, $pn_numero_registros = 0, $pa_order_by = null, $ps_order = null, $pa_log_info = null, $pn_idioma_codigo = 1, $pb_retornar_ramos_inferiores = true) { if (!isset($pa_filtros_busca["selecao_usuario_compartilhamento_codigo"])) $pa_filtros_busca["selecao_usuario_codigo"] = $_SESSION["usuario_logado_codigo"]; @@ -285,7 +285,7 @@ public function ler_lista($pa_filtros_busca = null, $ps_visualizacao = "lista", return parent::ler_lista($pa_filtros_busca, $ps_visualizacao, $pn_primeiro_registro, $pn_numero_registros, $pa_order_by, $ps_order, $pa_log_info, $pn_idioma_codigo); } - public function ler_numero_registros($pa_filtros_busca = null, $pa_log_info = null) + public function ler_numero_registros($pa_filtros_busca = null, $pa_log_info = null, $pb_retornar_ramos_inferiores = true) { $pa_filtros_busca["selecao_usuario_codigo"] = $_SESSION["usuario_logado_codigo"]; diff --git a/src/lib/system/tipo_selecao.php b/src/lib/system/tipo_selecao.php index 9fd22a7..76edd5d 100644 --- a/src/lib/system/tipo_selecao.php +++ b/src/lib/system/tipo_selecao.php @@ -24,7 +24,7 @@ public function ler($pn_codigo, $ps_visualizacao = 'lista', $pn_idioma_codigo = return $va_resultado; } - public function ler_lista($pa_filtros_busca = null, $ps_visualizacao = "lista", $pn_primeiro_registro = 0, $pn_numero_registros = 20, $pa_order_by = null, $ps_order = null, $pa_log_info = null, $pn_idioma_codigo = 1) + public function ler_lista($pa_filtros_busca = null, $ps_visualizacao = "lista", $pn_primeiro_registro = 0, $pn_numero_registros = 20, $pa_order_by = null, $ps_order = null, $pa_log_info = null, $pn_idioma_codigo = 1, $pb_retornar_ramos_inferiores = true) { $va_itens = array(); $va_resultado = array(); diff --git a/src/lib/system/tipo_usuario.php b/src/lib/system/tipo_usuario.php index 7530a3d..97da94d 100644 --- a/src/lib/system/tipo_usuario.php +++ b/src/lib/system/tipo_usuario.php @@ -24,7 +24,7 @@ public function ler($pn_codigo, $ps_visualizacao = 'lista', $pn_idioma_codigo = return $va_resultado; } - public function ler_lista($pa_filtros_busca = null, $ps_visualizacao = "lista", $pn_primeiro_registro = 0, $pn_numero_registros = 20, $pa_order_by = null, $ps_order = null, $pa_log_info = null, $pn_idioma_codigo = 1) + public function ler_lista($pa_filtros_busca = null, $ps_visualizacao = "lista", $pn_primeiro_registro = 0, $pn_numero_registros = 20, $pa_order_by = null, $ps_order = null, $pa_log_info = null, $pn_idioma_codigo = 1, $pb_retornar_ramos_inferiores = true) { $va_itens = array(); $va_resultado = array(); diff --git a/src/lib/system/tipo_visualizacao.php b/src/lib/system/tipo_visualizacao.php index 6f00f11..3bb8230 100755 --- a/src/lib/system/tipo_visualizacao.php +++ b/src/lib/system/tipo_visualizacao.php @@ -27,7 +27,7 @@ public function ler($pn_codigo, $ps_visualizacao = 'lista', $pn_idioma_codigo = return $va_resultado; } - public function ler_lista($pa_filtros_busca = null, $ps_visualizacao = "lista", $pn_primeiro_registro = 0, $pn_numero_registros = 20, $pa_order_by = null, $ps_order = null, $pa_log_info = null, $pn_idioma_codigo = 1) + public function ler_lista($pa_filtros_busca = null, $ps_visualizacao = "lista", $pn_primeiro_registro = 0, $pn_numero_registros = 20, $pa_order_by = null, $ps_order = null, $pa_log_info = null, $pn_idioma_codigo = 1, $pb_retornar_ramos_inferiores = true) { $va_itens = array(); $va_resultado = array(); diff --git a/src/lib/system/usuario_base.php b/src/lib/system/usuario_base.php index 9375511..d362fe5 100644 --- a/src/lib/system/usuario_base.php +++ b/src/lib/system/usuario_base.php @@ -214,7 +214,7 @@ public function salvar($pa_valores, $pb_logar_operacao = true, $pn_idioma_codigo return parent::salvar($pa_valores, $pb_logar_operacao, $pn_idioma_codigo, true, "", $pb_sobrescrever); } -public function ler_numero_registros($pa_filtros_busca = null, $pa_log_info = null) +public function ler_numero_registros($pa_filtros_busca = null, $pa_log_info = null, $pb_retornar_ramos_inferiores = true) { if (isset($pa_filtros_busca["instituicao_codigo"])) $pa_filtros_busca["usuario_instituicao_codigo"] = $pa_filtros_busca["instituicao_codigo"]; @@ -222,7 +222,7 @@ public function ler_numero_registros($pa_filtros_busca = null, $pa_log_info = nu return parent::ler_numero_registros($pa_filtros_busca, $pa_log_info); } -public function ler_lista($pa_filtros_busca = null, $ps_visualizacao = "lista", $pn_primeiro_registro = 0, $pn_numero_registros = 20, $pa_order_by = null, $ps_order = null, $pa_log_info = null, $pn_idioma_codigo = 1, $pb_login = false) +public function ler_lista($pa_filtros_busca = null, $ps_visualizacao = "lista", $pn_primeiro_registro = 0, $pn_numero_registros = 20, $pa_order_by = null, $ps_order = null, $pa_log_info = null, $pn_idioma_codigo = 1, $pb_retornar_ramos_inferiores = true) { if (isset($pa_filtros_busca["instituicao_codigo"])) $pa_filtros_busca["usuario_instituicao_codigo"] = $pa_filtros_busca["instituicao_codigo"]; diff --git a/src/vendors/simplexlsx/CHANGELOG.md b/src/vendors/simplexlsx/CHANGELOG.md new file mode 100644 index 0000000..49faf8e --- /dev/null +++ b/src/vendors/simplexlsx/CHANGELOG.md @@ -0,0 +1,293 @@ +# Changelog + +## 1.0.18 (2023-02-04) +* fixed regex to detect date/datetime in cell +* added $this->sheetMeta($worksheetIndex = null) to get metadata from workbook.xml +* added $this->isHiddenSheet($worksheetIndex) +* deleted $this->sheetNemes (use $this-sheetMetadata) + +## 1.0.17 (2022-10-13) + +* fixed readRowsEx (Undefined index: fontId) + +## 1.0.16 (2022-03-18) + +* fixed rowsEx(), _format_ returns now + +## 1.0.15 (2022-03-11) + +* Added requirements PHP 5.5+ in composer.json and README.md + +## 1.0.14 (2022-03-01) + +* PHP 5 generators capability, thx [maxiben](https://github.com/maxiben) + +## 1.0.13 (2022-02-22) + +* fixed basic usage example + +## 1.0.12 (2022-02-21) + +* 1.0 VERSION: Memory and styles +* PHP 5.5+, namespace `Shuchkin`, 4 spaces indents +* memory: added readRows() and readRowsEx() returns Generator. Help to read huge files +* memory: in my tests ~100k rowsEx() used 880 MB, readRowsEx() used 162 MB +* memory: added SimpleXLSXEx companion class for extract styles, used in rowsEx & toHTMLEx() only +* styles: alignment, fonts, fills, borders +* styles: rowsEx() return style info, cell width & height, css to apply in TD tag +* styles: added toHTMLEx() to export worksheet to HTML formatted table +* fixed author in license.md +* fixed examples + +## 0.9.11 (2022-02-05) + +* type "str" (formula and value) + +## 0.9.10 (2022-02-04) + +* class namespaced as Shuchkin\SimpleXLSX +* fixed reading from XML datetime as float and datetime as ISO + +## 0.8.33 (2022-01-23) + +* getting xml error + +## 0.8.32 (2022-01-22) + +* added LIBXML_COMPACT | LIBXML_PARSEHUGE + +## 0.8.31 (2021-12-01) + +* added $xlsx->activeSheet (thx reptile) + +## 0.8.30 (2021-12-01) + +* added $limit to $xlsx->rows( $sheetIndex = 0, $limit = 0 ) and to $xlsx->rowsEx( $seetIndex = 0, $limit = 0) +* Anyway SimpleXML loaded all XML data, so memory economy is minimal + +## 0.8.29 (2021-10-28) +* +* prevent not exists `cols` notice +* if cell type undefined, then parse it as number + +## 0.8.27 (2021-09-30) +* [] to array() for PHP 5.2 backward compatibility. Tested from PHP 5.2.7 to 8.0.9 + +## 0.8.26 (2021-08-24) + +* Fixed datetime type detection + +## 0.8.25 (2021-07-28) + +* ::rowsEx() - returns *hidden* flag, for hidden cells + +## 0.8.24 (2021-05-18) + +* Extract internal links + +## 0.8.23 (2021-04-20) + +* x10 fastest getCell, thx [Jonowa](https://github.com/shuchkin/simplexlsx/issues/102) +* for xpath idea / all private methods protected now. + +## 0.8.22 (2021-04-20) + +* fixed lost hash of hyperlinks + +## 0.8.21 (2021-01-11) + +* libxml_disable_entity_loader and PHP 8, thx [iKlsR](https://github.com/shuchkin/simplexlsx/issues/96) + +## 0.8.19 (2020-07-28) + +* fixed empty shared strings xml + +## 0.8.18 (2020-07-21) + +* fixed hyperlinks + +## 0.8.17 (2020-06-15) + +* fixed version number, added relative pathes a/../b support in relations + +## 0.8.16 (2020-06-14) + +* fixed abs pathes in relations + +## 0.8.15 (2020-04-28) + +* fixed LibreOffice xml specificity, thx [stephengmatthews](https://github.com/shuchkin/simplexlsx/issues/77) + +## 0.8.14 (2020-04-03) + +* fixed Office for Mac relations + +## 0.8.13 (2020-02-19) + +* removed skipEmptyRows property (xml optimization always), added static parseFile & parseData + +## 0.8.12 (2020-01-22) + +* remove empty rows (opencalc) + +## 0.8.11 (2020-01-20) + +* changed formats source priority + +## 0.8.10 (2019-11-07) + +* skipEmptyRows improved + +## 0.8.9 (2019-08-15) + +* fixed release version + +## 0.8.8 (2019-06-19) + +* removed list( $x, $y ), added bool $xlsx->skipEmptyRows, $xlsx->parseFile( $filename ), $xlsx->parseData( $data ), release 0.8.8 + +## 0.8.7 (2019-04-18) + +* empty rows fixed, release 0.8.7 + +## 0.8.6 (2019-04-16) + +* 1900/1904 bug fixed + +## 0.8.5 (2019-03-07) + +* SimpleXLSX::ParseErrno(), $xlsx->errno() returns error code + +## 0.8.4 (2019-02-14) + +* detect datetime values, mb_string.func_overload=2 support .!. Bitrix + +## 0.8.3 (2018-11-14) + +* getCell - fixed empty cells and rows, safe now, but very slow + +## 0.8.2 (2018-11-09) + +* fix empty cells and rows in rows() and rowsEx(), added setDateTimeFormat( $see_php_date_func ) + +## 0.8.1 + +* rename simplexlsx.php to SimpleXLSX.php, rename parse_error to parseError fix _columnIndex, add ->toHTML(), GNU to MIT license + +## 0.7.13 (2018-06-18) + +* get sheet indexes bug fix + +## 0.7.12 (2018-06-17) + +* $worksheet_id to $worksheet_index, sheet numeration started 0 + +## 0.7.11 (2018-04-25) + +* rowsEx(), added row index "r" to cell info + +## 0.7.10 (2018-04-21) + +* fixed getCell, returns NULL if not exits + +## 0.7.9 (2018-03-17) + +* fixed sheetNames() (namespaced or not namespaced attr) + +## 0.7.8 (2018-01-15) + +* remove namespace prefixes (hardcoded) + +## 0.7.7 (2017-10-02) + +* XML External Entity (XXE) Prevention (]>) + +## 0.7.6 (2017-09-26) + +* if worksheet_id === 0 (default) then detect first sheet (for LibreOffice capabilities) + +## 0.7.5 (2017-09-10) + +* ->getCell() - fixed + +## 0.7.4 (2017-08-22) + +* ::parse_error() - to get last error in "static style" + +## 0.7.3 (2017-08-14) + +* ->_parse fixed relations reader, added ->getCell( sheet_id, address, format ) for direct cell reading + +## 0.7.2 (2017-05-13) + +* ::parse( $filename ) helper method + +## 0.7.1 (2017-03-29) + +* License added + +## 0.6.11 (2016-07-27) + +* fixed timestamp() + +## 0.6.10 (2016-06-10) + +* fixed search entries (UPPERCASE) + +## 0.6.9 (2015-04-12) + +* $xlsx->datetime_format to force dates out + +## 0.6.8 (2013-10-13) + +* fixed dimension() where 1 row only, fixed rowsEx() empty cells indexes (Daniel Stastka) + +## 0.6.7 (2013-08-10) + +* fixed unzip (mac), added $debug param to _constructor to display errors + +## 0.6.6 (2013-06-03) + +* +entryExists() + +## 0.6.5 (2013-03-18) + +* fixed sheetName() + +## 0.6.4 (2013-03-13) + +* rowsEx(), _parse(): fixed date column type & format detection + +## 0.6.3 (2013-03-13) + +* rowsEx(): fixed formulas, added date type 'd', added format 'format' + dimension(): fixed empty sheet dimension + + sheetNames() - returns array( sheet_id => sheet_name, sheet_id2 => sheet_name2 ...) + +## 0.6.2 (2012-10-04) + +* fixed empty cells, rowsEx() returns type and formulas now + +## 0.6.1 (2012-09-14) + +* removed "raise exception" and fixed _unzip + +## 0.6 (2012-09-13) + +* success(), error(), __constructor( $filename, $is_data = false ) + +## 0.5.1 (2012-09-13) + +* sheetName() fixed + +## 0.5 (2012-09-12) + +* sheetName() + +## 0.4 + +* sheets(), sheetsCount(), unixstamp( $excelDateTime ) + +## 0.3 + +* fixed empty cells (Gonzo patch) \ No newline at end of file diff --git a/src/vendors/simplexlsx/README.md b/src/vendors/simplexlsx/README.md new file mode 100644 index 0000000..b250c0d --- /dev/null +++ b/src/vendors/simplexlsx/README.md @@ -0,0 +1,328 @@ +# SimpleXLSX class (Official) +[](https://packagist.org/packages/shuchkin/simplexlsx) +[](https://github.com/shuchkin/simplexlsx/blob/master/license.md) [](https://github.com/shuchkin/simplexlsx/stargazers) [](https://github.com/shuchkin/simplexlsx/network) [](https://github.com/shuchkin/simplexlsx/issues) +[](https://opencollective.com/simplexlsx) +[](https://www.patreon.com/shuchkin) + +Parse and retrieve data from Excel XLSx files. MS Excel 2007 workbooks PHP reader. +No addiditional extensions need (internal unzip + standart SimpleXML parser). + +See also:
+[SimpleXLS](https://github.com/shuchkin/simplexls) old format MS Excel 97 php reader.
+[SimpleXLSXGen](https://github.com/shuchkin/simplexlsxgen) xlsx php writer. + +*Hey, bro, please ★ the package for my motivation :) and [donate](https://opencollective.com/simplexlsx) for more motivation!* + +**Sergey Shuchkin** + +## Basic Usage +```php +use Shuchkin\SimpleXLSX; + +if ( $xlsx = SimpleXLSX::parse('book.xlsx') ) { + print_r( $xlsx->rows() ); +} else { + echo SimpleXLSX::parseError(); +} +``` +``` +Array +( + [0] => Array + ( + [0] => ISBN + [1] => title + [2] => author + [3] => publisher + [4] => ctry + ) + + [1] => Array + ( + [0] => 618260307 + [1] => The Hobbit + [2] => J. R. R. Tolkien + [3] => Houghton Mifflin + [4] => USA + ) + +) +``` +## Installation +The recommended way to install this library is [through Composer](https://getcomposer.org). +[New to Composer?](https://getcomposer.org/doc/00-intro.md) + +This will install the latest supported version: +```bash +$ composer require shuchkin/simplexlsx +``` +or download PHP 5.5+ class [here](https://github.com/shuchkin/simplexlsx/blob/master/src/SimpleXLSX.php) + +## Basic methods +``` +// open +SimpleXLSX::parse( $filename, $is_data = false, $debug = false ): SimpleXLSX (or false) +SimpleXLSX::parseFile( $filename, $debug = false ): SimpleXLSX (or false) +SimpleXLSX::parseData( $data, $debug = false ): SimpleXLSX (or false) +// simple +$xlsx->rows($worksheetIndex = 0, $limit = 0): array +$xlsx->readRows($worksheetIndex = 0, $limit = 0): Generator - helps read huge xlsx +$xlsx->toHTML($worksheetIndex = 0, $limit = 0): string +// extended +$xlsx->rowsEx($worksheetIndex = 0, $limit = 0): array +$xlsx->readRowsEx($worksheetIndex = 0, $limit = 0): Generator - helps read huge xlsx with styles +$xlsx->toHTMLEx($worksheetIndex = 0, $limit = 0): string +// meta +$xlsx->dimension($worksheetIndex):array [num_cols, num_rows] +$xlsx->sheetsCount():int +$xlsx->sheetNames():array +$xlsx->sheetName($worksheetIndex):string +$xlsx->sheetMeta($worksheetIndex = null):array sheets metadata (null = all sheets) +$xlsx->isHiddenSheet($worksheetIndex):bool +$xlsx->getStyles():array +``` + +## Examples +### XLSX to html table +```php +echo SimpleXLSX::parse('book.xlsx')->toHTML(); +``` +or +```php +if ( $xlsx = SimpleXLSX::parse('book.xlsx') ) { + echo ''; + foreach( $xlsx->rows() as $r ) { + echo ''; + } + echo '
'.implode('', $r ).'
'; +} else { + echo SimpleXLSX::parseError(); +} +``` +or styled html table +```php +if ( $xlsx = SimpleXLSX::parse('book_styled.xlsx') ) { + echo $xlsx->toHTMLEx(); +} +``` +### XLSX read huge file, xlsx to csv +```php +if ( $xlsx = SimpleXLSX::parse( 'xlsx/books.xlsx' ) ) { + $f = fopen('book.csv', 'wb'); + foreach ( $xlsx->readRows() as $r ) { + fwrite($f, implode(',',$r) . PHP_EOL); + } + fclose($f); +} else { + echo SimpleXLSX::parseError(); +} +``` +### XLSX get sheet names and sheet indexes +```php +// Sheet numeration started 0 + +if ( $xlsx = SimpleXLSX::parse( 'xlsx/books.xlsx' ) ) { + print_r( $xlsx->sheetNames() ); + print_r( $xlsx->sheetName( $xlsx->activeSheet ) ); +} + +``` +``` +Array +( + [0] => Sheet1 + [1] => Sheet2 + [2] => Sheet3 +) +Sheet2 +``` +### Using rowsEx() to extract cell info +```php +$xlsx = SimpleXLSX::parse('book.xlsx'); +print_r( $xlsx->rowsEx() ); + +``` +``` +Array +( + [0] => Array + ( + [0] => Array + ( + [type] => s + [name] => A1 + [value] => ISBN + [href] => + [f] => + [format] => + [s] => 0 + [css] => color: #000000;font-family: Calibri;font-size: 17px; + [r] => 1 + [hidden] => + [width] => 13.7109375 + [height] => 0 + ) + + [1] => Array + ( + [type] => + [name] => B1 + [value] => 2016-04-12 13:41:00 + [href] => + [f] => + [format] => m/d/yy h:mm + [s] => 0 + [css] => color: #000000;font-family: Calibri;font-size: 17px; + [r] => 2 + [hidden] => 1 + [width] => 16.5703125 + [height] => 0 + ) +``` + + + + + + + + + + + + +
typecell type
namecell name (A1, B11)
valuecell value (1233, 1233.34, 2022-02-21 00:00:00, String)
fformula
sstyle index, use $xlsx->cellFormats[ $index ] to get style
cssgenerated cell CSS
rrow index
hiddenhidden row or column
widthwidth in custom units
heightheight in points (pt, 1/72 in)
+ +### Select Sheet +```php +$xlsx = SimpleXLSX::parse('book.xlsx'); +// Sheet numeration started 0, we select second worksheet +foreach( $xlsx->rows(1) as $r ) { +// ... +} +``` +### Get sheet by index +```php +$xlsx = SimpleXLSX::parse('book.xlsx'); +echo 'Sheet Name 2 = '.$xlsx->sheetName(1); +``` +### XLSX::parse remote data +```php +if ( $xlsx = SimpleXLSX::parse('https://www.example.com/example.xlsx' ) ) { + $dim = $xlsx->dimension(1); // don't trust dimension extracted from xml + $num_cols = $dim[0]; + $num_rows = $dim[1]; + echo $xlsx->sheetName(1).':'.$num_cols.'x'.$num_rows; +} else { + echo SimpleXLSX::parseError(); +} +``` +### XLSX::parse memory data +```php +// For instance $data is a data from database or cache +if ( $xlsx = SimpleXLSX::parseData( $data ) ) { + print_r( $xlsx->rows() ); +} else { + echo SimpleXLSX::parseError(); +} +``` +### Get Cell (slow) +```php +echo $xlsx->getCell(0, 'B2'); // The Hobbit +``` +### DateTime helpers +```php +// default SimpleXLSX datetime format is YYYY-MM-DD HH:MM:SS (ISO, MySQL) +echo $xlsx->getCell(0,'C2'); // 2016-04-12 13:41:00 + +// custom datetime format +$xlsx->setDateTimeFormat('d.m.Y H:i'); +echo $xlsx->getCell(0,'C2'); // 12.04.2016 13:41 + +// unixstamp +$xlsx->setDateTimeFormat('U'); +$ts = $xlsx->getCell(0,'C2'); // 1460468460 +echo gmdate('Y-m-d', $ts); // 2016-04-12 +echo gmdate('H:i:s', $ts); // 13:41:00 + +// raw excel value +$xlsx->setDateTimeFormat( NULL ); // returns as excel datetime +$xd = $xlsx->getCell(0,'C2'); // 42472.570138889 +echo gmdate('m/d/Y', $xlsx->unixstamp( $xd )); // 04/12/2016 +echo gmdate('H:i:s', $xlsx->unixstamp( $xd )); // 13:41:00 +``` +### Rows with header values as keys +```php +if ( $xlsx = SimpleXLSX::parse('books.xlsx')) { + // Produce array keys from the array values of 1st array element + $header_values = $rows = []; + foreach ( $xlsx->rows() as $k => $r ) { + if ( $k === 0 ) { + $header_values = $r; + continue; + } + $rows[] = array_combine( $header_values, $r ); + } + print_r( $rows ); +} +``` +``` +Array +( + [0] => Array + ( + [ISBN] => 618260307 + [title] => The Hobbit + [author] => J. R. R. Tolkien + [publisher] => Houghton Mifflin + [ctry] => USA + ) + [1] => Array + ( + [ISBN] => 908606664 + [title] => Slinky Malinki + [author] => Lynley Dodd + [publisher] => Mallinson Rendel + [ctry] => NZ + ) +) +``` +### Debug +```php +use Shuchkin\SimpleXLSX; + +ini_set('error_reporting', E_ALL ); +ini_set('display_errors', 1 ); + +if ( $xlsx = SimpleXLSX::parseFile('books.xlsx', true ) ) { + echo $xlsx->toHTML(); +} else { + echo SimpleXLSX::parseError(); +} +``` +### Classic OOP style +```php +use SimpleXLSX; + +$xlsx = new SimpleXLSX('books.xlsx'); // try...catch +if ( $xlsx->success() ) { + foreach( $xlsx->rows() as $r ) { + // ... + } +} else { + echo 'xlsx error: '.$xlsx->error(); +} +``` +More examples [here](https://github.com/shuchkin/simplexlsx/tree/master/examples) + +### Error Codes +SimpleXLSX::ParseErrno(), $xlsx->errno()
+ + + + + + + + +
codemessagecomment
1File not foundWhere file? UFO?
2Unknown archive formatZIP?
3XML-entry parser errorbad XML
4XML-entry not foundbad ZIP archive
5Entry not foundFile not found in ZIP archive
6Worksheet not foundNot exists
\ No newline at end of file diff --git a/src/vendors/simplexlsx/license.md b/src/vendors/simplexlsx/license.md new file mode 100644 index 0000000..0c1edb1 --- /dev/null +++ b/src/vendors/simplexlsx/license.md @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2012-2022 Sergey Shuchkin sergey.shuchkin@gmail.com + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/src/vendors/simplexlsx/src/SimpleXLSX.php b/src/vendors/simplexlsx/src/SimpleXLSX.php new file mode 100644 index 0000000..787ed77 --- /dev/null +++ b/src/vendors/simplexlsx/src/SimpleXLSX.php @@ -0,0 +1,1254 @@ +rows() as $r) { + * print_r( $r ); + * } + * } else { + * echo SimpleXLSX::parseError(); + * } + * + * Example 2: html table + * if ( $xlsx = SimpleXLSX::parse('book.xlsx') ) { + * echo $xlsx->toHTML(); + * } else { + * echo SimpleXLSX::parseError(); + * } + * + * Example 3: rowsEx + * $xlsx = SimpleXLSX::parse('book.xlsx'); + * foreach ( $xlsx->rowsEx() as $r ) { + * print_r( $r ); + * } + * + * Example 4: select worksheet + * $xlsx = SimpleXLSX::parse('book.xlsx'); + * foreach( $xlsx->rows(1) as $r ) { // second worksheet + * print_t( $r ); + * } + * + * Example 5: IDs and worksheet names + * $xlsx = SimpleXLSX::parse('book.xlsx'); + * print_r( $xlsx->sheetNames() ); // array( 0 => 'Sheet 1', 1 => 'Catalog' ); + * + * Example 6: get sheet name by index + * $xlsx = SimpleXLSX::parse('book.xlsx'); + * echo 'Sheet Name 2 = '.$xlsx->sheetName(1); + * + * Example 7: getCell (very slow) + * echo $xlsx->getCell(1,'D12'); // reads D12 cell from second sheet + * + * Example 8: read data + * if ( $xlsx = SimpleXLSX::parseData( file_get_contents('http://www.example.com/example.xlsx') ) ) { + * $dim = $xlsx->dimension(1); + * $num_cols = $dim[0]; + * $num_rows = $dim[1]; + * echo $xlsx->sheetName(1).':'.$num_cols.'x'.$num_rows; + * } else { + * echo SimpleXLSX::parseError(); + * } + * + * Example 9: old style + * $xlsx = new SimpleXLSX('book.xlsx'); + * if ( $xlsx->success() ) { + * print_r( $xlsx->rows() ); + * } else { + * echo 'xlsx error: '.$xlsx->error(); + * } + */ +class SimpleXLSX +{ + // Don't remove this string! Created by Sergey Shuchkin sergey.shuchkin@gmail.com + public static $CF = [ // Cell formats + 0 => 'General', + 1 => '0', + 2 => '0.00', + 3 => '#,##0', + 4 => '#,##0.00', + 9 => '0%', + 10 => '0.00%', + 11 => '0.00E+00', + 12 => '# ?/?', + 13 => '# ??/??', + 14 => 'mm-dd-yy', + 15 => 'd-mmm-yy', + 16 => 'd-mmm', + 17 => 'mmm-yy', + 18 => 'h:mm AM/PM', + 19 => 'h:mm:ss AM/PM', + 20 => 'h:mm', + 21 => 'h:mm:ss', + 22 => 'm/d/yy h:mm', + + 37 => '#,##0 ;(#,##0)', + 38 => '#,##0 ;[Red](#,##0)', + 39 => '#,##0.00;(#,##0.00)', + 40 => '#,##0.00;[Red](#,##0.00)', + + 44 => '_("$"* #,##0.00_);_("$"* \(#,##0.00\);_("$"* "-"??_);_(@_)', + 45 => 'mm:ss', + 46 => '[h]:mm:ss', + 47 => 'mmss.0', + 48 => '##0.0E+0', + 49 => '@', + + 27 => '[$-404]e/m/d', + 30 => 'm/d/yy', + 36 => '[$-404]e/m/d', + 50 => '[$-404]e/m/d', + 57 => '[$-404]e/m/d', + + 59 => 't0', + 60 => 't0.00', + 61 => 't#,##0', + 62 => 't#,##0.00', + 67 => 't0%', + 68 => 't0.00%', + 69 => 't# ?/?', + 70 => 't# ??/??', + ]; + public $nf = []; // number formats + public $cellFormats = []; // cellXfs + public $datetimeFormat = 'Y-m-d H:i:s'; + public $debug; + public $activeSheet = 0; + public $rowsExReader; + + /* @var SimpleXMLElement[] $sheets */ + protected $sheets; + protected $sheetFiles = []; + protected $sheetMetaData = []; + // scheme + public $styles; + protected $hyperlinks; + /* @var array[] $package */ + protected $package; + protected $sharedstrings; + protected $date1904 = 0; + + + /* + private $date_formats = array( + 0xe => "d/m/Y", + 0xf => "d-M-Y", + 0x10 => "d-M", + 0x11 => "M-Y", + 0x12 => "h:i a", + 0x13 => "h:i:s a", + 0x14 => "H:i", + 0x15 => "H:i:s", + 0x16 => "d/m/Y H:i", + 0x2d => "i:s", + 0x2e => "H:i:s", + 0x2f => "i:s.S" + ); + private $number_formats = array( + 0x1 => "%1.0f", // "0" + 0x2 => "%1.2f", // "0.00", + 0x3 => "%1.0f", //"#,##0", + 0x4 => "%1.2f", //"#,##0.00", + 0x5 => "%1.0f", //"$#,##0;($#,##0)", + 0x6 => '$%1.0f', //"$#,##0;($#,##0)", + 0x7 => '$%1.2f', //"$#,##0.00;($#,##0.00)", + 0x8 => '$%1.2f', //"$#,##0.00;($#,##0.00)", + 0x9 => '%1.0f%%', //"0%" + 0xa => '%1.2f%%', //"0.00%" + 0xb => '%1.2f', //"0.00E00", + 0x25 => '%1.0f', //"#,##0;(#,##0)", + 0x26 => '%1.0f', //"#,##0;(#,##0)", + 0x27 => '%1.2f', //"#,##0.00;(#,##0.00)", + 0x28 => '%1.2f', //"#,##0.00;(#,##0.00)", + 0x29 => '%1.0f', //"#,##0;(#,##0)", + 0x2a => '$%1.0f', //"$#,##0;($#,##0)", + 0x2b => '%1.2f', //"#,##0.00;(#,##0.00)", + 0x2c => '$%1.2f', //"$#,##0.00;($#,##0.00)", + 0x30 => '%1.0f'); //"##0.0E0"; + // }}} + */ + protected $errno = 0; + protected $error = false; + /** + * @var false|SimpleXMLElement + */ + public $theme; + + + public function __construct($filename = null, $is_data = null, $debug = null) + { + if ($debug !== null) { + $this->debug = $debug; + } + $this->package = [ + 'filename' => '', + 'mtime' => 0, + 'size' => 0, + 'comment' => '', + 'entries' => [] + ]; + if ($filename && $this->_unzip($filename, $is_data)) { + $this->_parse(); + } + } + + protected function _unzip($filename, $is_data = false) + { + + if ($is_data) { + $this->package['filename'] = 'default.xlsx'; + $this->package['mtime'] = time(); + $this->package['size'] = $this->_strlen($filename); + + $vZ = $filename; + } else { + if (!is_readable($filename)) { + $this->error(1, 'File not found ' . $filename); + + return false; + } + + // Package information + $this->package['filename'] = $filename; + $this->package['mtime'] = filemtime($filename); + $this->package['size'] = filesize($filename); + + // Read file + $vZ = file_get_contents($filename); + } + // Cut end of central directory + /* $aE = explode("\x50\x4b\x05\x06", $vZ); + + if (count($aE) == 1) { + $this->error('Unknown format'); + return false; + } + */ + // Explode to each part + $aE = explode("\x50\x4b\x03\x04", $vZ); + array_shift($aE); + + $aEL = count($aE); + if ($aEL === 0) { + $this->error(2, 'Unknown archive format'); + + return false; + } + // Search central directory end record + $last = $aE[$aEL - 1]; + $last = explode("\x50\x4b\x05\x06", $last); + if (count($last) !== 2) { + $this->error(2, 'Unknown archive format'); + + return false; + } + // Search central directory + $last = explode("\x50\x4b\x01\x02", $last[0]); + if (count($last) < 2) { + $this->error(2, 'Unknown archive format'); + + return false; + } + $aE[$aEL - 1] = $last[0]; + + // Loop through the entries + foreach ($aE as $vZ) { + $aI = []; + $aI['E'] = 0; + $aI['EM'] = ''; + // Retrieving local file header information +// $aP = unpack('v1VN/v1GPF/v1CM/v1FT/v1FD/V1CRC/V1CS/V1UCS/v1FNL', $vZ); + $aP = unpack('v1VN/v1GPF/v1CM/v1FT/v1FD/V1CRC/V1CS/V1UCS/v1FNL/v1EFL', $vZ); + + // Check if data is encrypted +// $bE = ($aP['GPF'] && 0x0001) ? TRUE : FALSE; +// $bE = false; + $nF = $aP['FNL']; + $mF = $aP['EFL']; + + // Special case : value block after the compressed data + if ($aP['GPF'] & 0x0008) { + $aP1 = unpack('V1CRC/V1CS/V1UCS', $this->_substr($vZ, -12)); + + $aP['CRC'] = $aP1['CRC']; + $aP['CS'] = $aP1['CS']; + $aP['UCS'] = $aP1['UCS']; + // 2013-08-10 + $vZ = $this->_substr($vZ, 0, -12); + if ($this->_substr($vZ, -4) === "\x50\x4b\x07\x08") { + $vZ = $this->_substr($vZ, 0, -4); + } + } + + // Getting stored filename + $aI['N'] = $this->_substr($vZ, 26, $nF); + $aI['N'] = str_replace('\\', '/', $aI['N']); + + if ($this->_substr($aI['N'], -1) === '/') { + // is a directory entry - will be skipped + continue; + } + + // Truncate full filename in path and filename + $aI['P'] = dirname($aI['N']); + $aI['P'] = ($aI['P'] === '.') ? '' : $aI['P']; + $aI['N'] = basename($aI['N']); + + $vZ = $this->_substr($vZ, 26 + $nF + $mF); + + if ($this->_strlen($vZ) !== (int)$aP['CS']) { // check only if availabled + $aI['E'] = 1; + $aI['EM'] = 'Compressed size is not equal with the value in header information.'; + } +// } elseif ( $bE ) { +// $aI['E'] = 5; +// $aI['EM'] = 'File is encrypted, which is not supported from this class.'; +/* } else { + switch ($aP['CM']) { + case 0: // Stored + // Here is nothing to do, the file ist flat. + break; + case 8: // Deflated + $vZ = gzinflate($vZ); + break; + case 12: // BZIP2 + if (extension_loaded('bz2')) { + $vZ = bzdecompress($vZ); + } else { + $aI['E'] = 7; + $aI['EM'] = 'PHP BZIP2 extension not available.'; + } + break; + default: + $aI['E'] = 6; + $aI['EM'] = "De-/Compression method {$aP['CM']} is not supported."; + } + if (!$aI['E']) { + if ($vZ === false) { + $aI['E'] = 2; + $aI['EM'] = 'Decompression of data failed.'; + } elseif ($this->_strlen($vZ) !== (int)$aP['UCS']) { + $aI['E'] = 3; + $aI['EM'] = 'Uncompressed size is not equal with the value in header information.'; + } elseif (crc32($vZ) !== $aP['CRC']) { + $aI['E'] = 4; + $aI['EM'] = 'CRC32 checksum is not equal with the value in header information.'; + } + } + } +*/ + + // DOS to UNIX timestamp + $aI['T'] = mktime( + ($aP['FT'] & 0xf800) >> 11, + ($aP['FT'] & 0x07e0) >> 5, + ($aP['FT'] & 0x001f) << 1, + ($aP['FD'] & 0x01e0) >> 5, + $aP['FD'] & 0x001f, + (($aP['FD'] & 0xfe00) >> 9) + 1980 + ); + + $this->package['entries'][] = [ + 'data' => $vZ, + 'ucs' => (int)$aP['UCS'], // ucompresses size + 'cm' => $aP['CM'], // compressed method + 'cs' => isset($aP['CS']) ? (int) $aP['CS'] : 0, // compresses size + 'crc' => $aP['CRC'], + 'error' => $aI['E'], + 'error_msg' => $aI['EM'], + 'name' => $aI['N'], + 'path' => $aI['P'], + 'time' => $aI['T'] + ]; + } // end for each entries + + return true; + } + + protected function _strlen($str) + { + return (ini_get('mbstring.func_overload') & 2) ? mb_strlen($str, '8bit') : strlen($str); + } + + public function error($num = null, $str = null) + { + if ($num) { + $this->errno = $num; + $this->error = $str; + if ($this->debug) { + trigger_error(__CLASS__ . ': ' . $this->error, E_USER_WARNING); + } + } + + return $this->error; + } + + protected function _substr($str, $start, $length = null) + { + return (ini_get('mbstring.func_overload') & 2) ? mb_substr($str, $start, ($length === null) ? mb_strlen($str, '8bit') : $length, '8bit') : substr($str, $start, ($length === null) ? strlen($str) : $length); + } + + protected function _parse() + { + // Document data holders + $this->sharedstrings = []; + $this->sheets = []; +// $this->styles = array(); +// $m1 = 0; // memory_get_peak_usage( true ); + // Read relations and search for officeDocument + if ($relations = $this->getEntryXML('_rels/.rels')) { + foreach ($relations->Relationship as $rel) { + $rel_type = basename(trim((string)$rel['Type'])); // officeDocument + $rel_target = $this->_getTarget('', (string)$rel['Target']); // /xl/workbook.xml or xl/workbook.xml + + if ($rel_type === 'officeDocument' && $workbook = $this->getEntryXML($rel_target)) { + $index_rId = []; // [0 => rId1] + + $index = 0; + foreach ($workbook->sheets->sheet as $s) { + $a = []; + foreach ($s->attributes() as $k => $v) { + $a[(string)$k] = (string)$v; + } + $this->sheetMetaData[$index] = $a; + $index_rId[$index] = (string)$s['id']; + $index++; + } + if ((int)$workbook->workbookPr['date1904'] === 1) { + $this->date1904 = 1; + } + + + if ($workbookRelations = $this->getEntryXML(dirname($rel_target) . '/_rels/workbook.xml.rels')) { + // Loop relations for workbook and extract sheets... + foreach ($workbookRelations->Relationship as $workbookRelation) { + $wrel_type = basename(trim((string)$workbookRelation['Type'])); // worksheet + $wrel_path = $this->_getTarget(dirname($rel_target), (string)$workbookRelation['Target']); + if (!$this->entryExists($wrel_path)) { + continue; + } + + + if ($wrel_type === 'worksheet') { // Sheets + if ($sheet = $this->getEntryXML($wrel_path)) { + $index = array_search((string)$workbookRelation['Id'], $index_rId, true); + $this->sheets[$index] = $sheet; + $this->sheetFiles[$index] = $wrel_path; + } + } elseif ($wrel_type === 'sharedStrings') { + if ($sharedStrings = $this->getEntryXML($wrel_path)) { + foreach ($sharedStrings->si as $val) { + if (isset($val->t)) { + $this->sharedstrings[] = (string)$val->t; + } elseif (isset($val->r)) { + $this->sharedstrings[] = $this->_parseRichText($val); + } + } + } + } elseif ($wrel_type === 'styles') { + $this->styles = $this->getEntryXML($wrel_path); + + // number formats + $this->nf = []; + if (isset($this->styles->numFmts->numFmt)) { + foreach ($this->styles->numFmts->numFmt as $v) { + $this->nf[(int)$v['numFmtId']] = (string)$v['formatCode']; + } + } + + $this->cellFormats = []; + if (isset($this->styles->cellXfs->xf)) { + foreach ($this->styles->cellXfs->xf as $v) { + $x = [ + 'format' => null + ]; + foreach ($v->attributes() as $k1 => $v1) { + $x[ $k1 ] = (int) $v1; + } + if (isset($x['numFmtId'])) { + if (isset($this->nf[$x['numFmtId']])) { + $x['format'] = $this->nf[$x['numFmtId']]; + } elseif (isset(self::$CF[$x['numFmtId']])) { + $x['format'] = self::$CF[$x['numFmtId']]; + } + } + + $this->cellFormats[] = $x; + } + } + } elseif ($wrel_type === 'theme') { + $this->theme = $this->getEntryXML($wrel_path); + } + } + + break; + } + // reptile hack :: find active sheet from workbook.xml + foreach ($workbook->bookViews->workbookView as $s) { + if (!empty($s['activeTab'])) { + $this->activeSheet = (int)$s['activeTab']; + } + } + } + } + } + +// $m2 = memory_get_peak_usage(true); +// echo __FUNCTION__.' M='.round( ($m2-$m1) / 1048576, 2).'MB'.PHP_EOL; + + if (count($this->sheets)) { + // Sort sheets + ksort($this->sheets); + + return true; + } + + return false; + } + + public function getEntryXML($name) + { + if ($entry_xml = $this->getEntryData($name)) { + $this->deleteEntry($name); // economy memory + // dirty remove namespace prefixes and empty rows + $entry_xml = preg_replace('/xmlns[^=]*="[^"]*"/i', '', $entry_xml); // remove namespaces + $entry_xml .= ' '; // force run garbage collector + $entry_xml = preg_replace('/[a-zA-Z0-9]+:([a-zA-Z0-9]+="[^"]+")/', '$1', $entry_xml); // remove namespaced attrs + $entry_xml .= ' '; + $entry_xml = preg_replace('/<[a-zA-Z0-9]+:([^>]+)>/', '<$1>', $entry_xml); // fix namespaced openned tags + $entry_xml .= ' '; + $entry_xml = preg_replace('/<\/[a-zA-Z0-9]+:([^>]+)>/', '', $entry_xml); // fix namespaced closed tags + $entry_xml .= ' '; + + if (strpos($name, '/sheet')) { // dirty skip empty rows + // remove + $entry_xml = preg_replace('/]+>\s*(\s*)+<\/row>/', '', $entry_xml, -1, $cnt); + $entry_xml .= ' '; + // remove + $entry_xml = preg_replace('/]*\/>/', '', $entry_xml, -1, $cnt2); + $entry_xml .= ' '; + // remove + $entry_xml = preg_replace('/]*><\/row>/', '', $entry_xml, -1, $cnt3); + $entry_xml .= ' '; + if ($cnt || $cnt2 || $cnt3) { + $entry_xml = preg_replace('//', '', $entry_xml); + $entry_xml .= ' '; + } +// file_put_contents( basename( $name ), $entry_xml ); // @to do comment!!! + } + $entry_xml = trim($entry_xml); + +// $m1 = memory_get_usage(); + // XML External Entity (XXE) Prevention, libxml_disable_entity_loader deprecated in PHP 8 + if (LIBXML_VERSION < 20900 && function_exists('libxml_disable_entity_loader')) { + $_old = libxml_disable_entity_loader(); + } + + $_old_uie = libxml_use_internal_errors(true); + + $entry_xmlobj = simplexml_load_string($entry_xml, 'SimpleXMLElement', LIBXML_COMPACT | LIBXML_PARSEHUGE); + + libxml_use_internal_errors($_old_uie); + + if (LIBXML_VERSION < 20900 && function_exists('libxml_disable_entity_loader')) { + /** @noinspection PhpUndefinedVariableInspection */ + libxml_disable_entity_loader($_old); + } + +// $m2 = memory_get_usage(); +// echo round( ($m2-$m1) / (1024 * 1024), 2).' MB'.PHP_EOL; + + if ($entry_xmlobj) { + return $entry_xmlobj; + } + $e = libxml_get_last_error(); + if ($e) { + $this->error(3, 'XML-entry ' . $name . ' parser error ' . $e->message . ' line ' . $e->line); + } + } else { + $this->error(4, 'XML-entry not found ' . $name); + } + + return false; + } + + // sheets numeration: 1,2,3.... + + public function getEntryData($name) + { + $name = ltrim(str_replace('\\', '/', $name), '/'); + $dir = $this->_strtoupper(dirname($name)); + $name = $this->_strtoupper(basename($name)); + foreach ($this->package['entries'] as &$entry) { + if ($this->_strtoupper($entry['path']) === $dir && $this->_strtoupper($entry['name']) === $name) { + if ($entry['error']) { + return false; + } + switch ($entry['cm']) { + case -1: + case 0: // Stored + // Here is nothing to do, the file ist flat. + break; + case 8: // Deflated + $entry['data'] = gzinflate($entry['data']); + break; + case 12: // BZIP2 + if (extension_loaded('bz2')) { + $entry['data'] = bzdecompress($entry['data']); + } else { + $entry['error'] = 7; + $entry['error_message'] = 'PHP BZIP2 extension not available.'; + } + break; + default: + $entry['error'] = 6; + $entry['error_msg'] = 'De-/Compression method '.$entry['cm'].' is not supported.'; + } + if (!$entry['error'] && $entry['cm'] > -1) { + $entry['cm'] = -1; + if ($entry['data'] === false) { + $entry['error'] = 2; + $entry['error_msg'] = 'Decompression of data failed.'; + } elseif ($this->_strlen($entry['data']) !== (int)$entry['ucs']) { + $entry['error'] = 3; + $entry['error_msg'] = 'Uncompressed size is not equal with the value in header information.'; + } elseif (crc32($entry['data']) !== $entry['crc']) { + $entry['error'] = 4; + $entry['error_msg'] = 'CRC32 checksum is not equal with the value in header information.'; + } + } + + return $entry['data']; + } + } + unset($entry); + $this->error(5, 'Entry not found ' . ($dir ? $dir . '/' : '') . $name); + + return false; + } + public function deleteEntry($name) + { + $name = ltrim(str_replace('\\', '/', $name), '/'); + $dir = $this->_strtoupper(dirname($name)); + $name = $this->_strtoupper(basename($name)); + foreach ($this->package['entries'] as $k => $entry) { + if ($this->_strtoupper($entry['path']) === $dir && $this->_strtoupper($entry['name']) === $name) { + unset($this->package['entries'][$k]); + return true; + } + } + return false; + } + + protected function _strtoupper($str) + { + return (ini_get('mbstring.func_overload') & 2) ? mb_strtoupper($str, '8bit') : strtoupper($str); + } + + protected function _getTarget($base, $target) + { + $target = trim($target); + if (strpos($target, '/') === 0) { + return $this->_substr($target, 1); + } + $target = ($base ? $base . '/' : '') . $target; + // a/b/../c -> a/c + $parts = explode('/', $target); + $abs = []; + foreach ($parts as $p) { + if ('.' === $p) { + continue; + } + if ('..' === $p) { + array_pop($abs); + } else { + $abs[] = $p; + } + } + return implode('/', $abs); + } + + /* + * @param string $name Filename in archive + * @return SimpleXMLElement|bool + */ + + public function entryExists($name) + { + // 0.6.6 + $dir = $this->_strtoupper(dirname($name)); + $name = $this->_strtoupper(basename($name)); + foreach ($this->package['entries'] as $entry) { + if ($this->_strtoupper($entry['path']) === $dir && $this->_strtoupper($entry['name']) === $name) { + return true; + } + } + + return false; + } + + protected function _parseRichText($is = null) + { + $value = []; + + if (isset($is->t)) { + $value[] = (string)$is->t; + } elseif (isset($is->r)) { + foreach ($is->r as $run) { + $value[] = (string)$run->t; + } + } + + return implode('', $value); + } + + public static function parseFile($filename, $debug = false) + { + return self::parse($filename, false, $debug); + } + + public static function parse($filename, $is_data = false, $debug = false) + { + $xlsx = new self(); + $xlsx->debug = $debug; + if ($xlsx->_unzip($filename, $is_data)) { + $xlsx->_parse(); + } + if ($xlsx->success()) { + return $xlsx; + } + self::parseError($xlsx->error()); + self::parseErrno($xlsx->errno()); + + return false; + } + + public function success() + { + return !$this->error; + } + + // https://github.com/shuchkin/simplexlsx#gets-extend-cell-info-by--rowsex + + public static function parseError($set = false) + { + static $error = false; + + return $set ? $error = $set : $error; + } + + public static function parseErrno($set = false) + { + static $errno = false; + + return $set ? $errno = $set : $errno; + } + + public function errno() + { + return $this->errno; + } + + public static function parseData($data, $debug = false) + { + return self::parse($data, true, $debug); + } + + + + public function worksheet($worksheetIndex = 0) + { + + + if (isset($this->sheets[$worksheetIndex])) { + $ws = $this->sheets[$worksheetIndex]; + + if (!isset($this->hyperlinks[$worksheetIndex]) && isset($ws->hyperlinks)) { + $this->hyperlinks[$worksheetIndex] = []; + $sheet_rels = str_replace('worksheets', 'worksheets/_rels', $this->sheetFiles[$worksheetIndex]) . '.rels'; + $link_ids = []; + + if ($rels = $this->getEntryXML($sheet_rels)) { + // hyperlink +// $rel_base = dirname( $sheet_rels ); + foreach ($rels->Relationship as $rel) { + $rel_type = basename(trim((string)$rel['Type'])); + if ($rel_type === 'hyperlink') { + $rel_id = (string)$rel['Id']; + $rel_target = (string)$rel['Target']; + $link_ids[$rel_id] = $rel_target; + } + } + } + foreach ($ws->hyperlinks->hyperlink as $hyperlink) { + $ref = (string)$hyperlink['ref']; + if ($this->_strpos($ref, ':') > 0) { // A1:A8 -> A1 + $ref = explode(':', $ref); + $ref = $ref[0]; + } +// $this->hyperlinks[ $worksheetIndex ][ $ref ] = (string) $hyperlink['display']; + $loc = (string)$hyperlink['location']; + $id = (string)$hyperlink['id']; + if ($id) { + $href = $link_ids[$id] . ($loc ? '#' . $loc : ''); + } else { + $href = $loc; + } + $this->hyperlinks[$worksheetIndex][$ref] = $href; + } + } + + return $ws; + } + $this->error(6, 'Worksheet not found ' . $worksheetIndex); + + return false; + } + + protected function _strpos($haystack, $needle, $offset = 0) + { + return (ini_get('mbstring.func_overload') & 2) ? mb_strpos($haystack, $needle, $offset, '8bit') : strpos($haystack, $needle, $offset); + } + + /** + * returns [numCols,numRows] of worksheet + * + * @param int $worksheetIndex + * + * @return array + */ + public function dimension($worksheetIndex = 0) + { + + if (($ws = $this->worksheet($worksheetIndex)) === false) { + return [0, 0]; + } + /* @var SimpleXMLElement $ws */ + + $ref = (string)$ws->dimension['ref']; + + if ($this->_strpos($ref, ':') !== false) { + $d = explode(':', $ref); + $idx = $this->getIndex($d[1]); + + return [$idx[0] + 1, $idx[1] + 1]; + } + /* + if ( $ref !== '' ) { // 0.6.8 + $index = $this->getIndex( $ref ); + + return [ $index[0] + 1, $index[1] + 1 ]; + } + */ + + // slow method + $maxC = $maxR = 0; + $iR = -1; + foreach ($ws->sheetData->row as $row) { + $iR++; + $iC = -1; + foreach ($row->c as $c) { + $iC++; + $idx = $this->getIndex((string)$c['r']); + $x = $idx[0]; + $y = $idx[1]; + if ($x > -1) { + if ($x > $maxC) { + $maxC = $x; + } + if ($y > $maxR) { + $maxR = $y; + } + } else { + if ($iC > $maxC) { + $maxC = $iC; + } + if ($iR > $maxR) { + $maxR = $iR; + } + } + } + } + + return [$maxC + 1, $maxR + 1]; + } + + public function getIndex($cell = 'A1') + { + + if (preg_match('/([A-Z]+)(\d+)/', $cell, $m)) { + $col = $m[1]; + $row = $m[2]; + + $colLen = $this->_strlen($col); + $index = 0; + + for ($i = $colLen - 1; $i >= 0; $i--) { + $index += (ord($col[$i]) - 64) * pow(26, $colLen - $i - 1); + } + + return [$index - 1, $row - 1]; + } + +// $this->error( 'Invalid cell index ' . $cell ); + + return [-1, -1]; + } + + public function value($cell) + { + // Determine data type + $dataType = (string)$cell['t']; + + if ($dataType === '' || $dataType === 'n') { // number + $s = (int)$cell['s']; + if ($s > 0 && isset($this->cellFormats[$s])) { + if (array_key_exists('format', $this->cellFormats[$s])) { + $format = $this->cellFormats[$s]['format']; + if (preg_match('/[mM]/', preg_replace('/\"[^"]+\"/', '', $format))) { // [mm]onth,AM|PM + $dataType = 'D'; + } + } else { + $dataType = 'n'; + } + } + } + + $value = ''; + + switch ($dataType) { + case 's': + // Value is a shared string + if ((string)$cell->v !== '') { + $value = $this->sharedstrings[(int)$cell->v]; + } + break; + + case 'str': // formula? + if ((string)$cell->v !== '') { + $value = (string)$cell->v; + } + break; + + case 'b': + // Value is boolean + $value = (string)$cell->v; + if ($value === '0') { + $value = false; + } elseif ($value === '1') { + $value = true; + } else { + $value = (bool)$cell->v; + } + + break; + + case 'inlineStr': + // Value is rich text inline + $value = $this->_parseRichText($cell->is); + + break; + + case 'e': + // Value is an error message + if ((string)$cell->v !== '') { + $value = (string)$cell->v; + } + break; + + case 'D': + // Date as float + if (!empty($cell->v)) { + $value = $this->datetimeFormat ? gmdate($this->datetimeFormat, $this->unixstamp((float)$cell->v)) : (float)$cell->v; + } + break; + + case 'd': + // Date as ISO YYYY-MM-DD + if ((string)$cell->v !== '') { + $value = (string)$cell->v; + } + break; + + default: + // Value is a string + $value = (string)$cell->v; + + // Check for numeric values + if (is_numeric($value)) { + /** @noinspection TypeUnsafeComparisonInspection */ + if ($value == (int)$value) { + $value = (int)$value; + } /** @noinspection TypeUnsafeComparisonInspection */ elseif ($value == (float)$value) { + $value = (float)$value; + } + } + } + + return $value; + } + + public function unixstamp($excelDateTime) + { + + $d = floor($excelDateTime); // days since 1900 or 1904 + $t = $excelDateTime - $d; + + if ($this->date1904) { + $d += 1462; + } + + $t = (abs($d) > 0) ? ($d - 25569) * 86400 + round($t * 86400) : round($t * 86400); + + return (int)$t; + } + + public function href($worksheetIndex, $cell) + { + $ref = (string)$cell['r']; + return isset($this->hyperlinks[$worksheetIndex][$ref]) ? $this->hyperlinks[$worksheetIndex][$ref] : ''; + } + + public function toHTML($worksheetIndex = 0) + { + $s = ''; + foreach ($this->readRows($worksheetIndex) as $r) { + $s .= ''; + foreach ($r as $c) { + $s .= ''; + } + $s .= "\r\n"; + } + $s .= '
' . ($c === '' ? ' ' : htmlspecialchars($c, ENT_QUOTES)) . '
'; + + return $s; + } + public function toHTMLEx($worksheetIndex = 0) + { + $s = ''; + $y = 0; + foreach ($this->readRowsEx($worksheetIndex) as $r) { + $s .= ''; + $x = 0; + foreach ($r as $c) { + $tag = 'td'; + $css = $c['css']; + if ($y === 0) { + $tag = 'th'; + $css .= $c['width'] ? 'width: '.round($c['width'] * 0.47, 2).'em;' : ''; + } + + if ($x === 0 && $c['height']) { + $css .= 'height: '.round($c['height'] * 1.3333).'px;'; + } + $s .= '<'.$tag.' style="'.$css.'" nowrap>' . ($c['value'] === '' ? ' ' : htmlspecialchars($c['value'], ENT_QUOTES)) . ''; + $x++; + } + $s .= "\r\n"; + $y++; + } + $s .= '
'; + + return $s; + } + public function rows($worksheetIndex = 0, $limit = 0) + { + return iterator_to_array($this->readRows($worksheetIndex, $limit), false); + } + // thx Gonzo + /** + * @param $worksheetIndex + * @param $limit + * @return \Generator + */ + public function readRows($worksheetIndex = 0, $limit = 0) + { + + if (($ws = $this->worksheet($worksheetIndex)) === false) { + return; + } + $dim = $this->dimension($worksheetIndex); + $numCols = $dim[0]; + $numRows = $dim[1]; + + $emptyRow = []; + for ($i = 0; $i < $numCols; $i++) { + $emptyRow[] = ''; + } + + $curR = 0; + $_limit = $limit; + /* @var SimpleXMLElement $ws */ + foreach ($ws->sheetData->row as $row) { + $r = $emptyRow; + $curC = 0; + foreach ($row->c as $c) { + // detect skipped cols + $idx = $this->getIndex((string)$c['r']); + $x = $idx[0]; + $y = $idx[1]; + + if ($x > -1) { + $curC = $x; + while ($curR < $y) { + yield $emptyRow; + $curR++; + $_limit--; + if ($_limit === 0) { + return; + } + } + } + $r[$curC] = $this->value($c); + $curC++; + } + yield $r; + + $curR++; + $_limit--; + if ($_limit === 0) { + return; + } + } + while ($curR < $numRows) { + yield $emptyRow; + $curR++; + $_limit--; + if ($_limit === 0) { + return; + } + } + } + + public function rowsEx($worksheetIndex = 0, $limit = 0) + { + return iterator_to_array($this->readRowsEx($worksheetIndex, $limit), false); + } + // https://github.com/shuchkin/simplexlsx#gets-extend-cell-info-by--rowsex + /** + * @param $worksheetIndex + * @param $limit + * @return \Generator|null + */ + public function readRowsEx($worksheetIndex = 0, $limit = 0) + { + if (!$this->rowsExReader) { + require_once __DIR__ . '/SimpleXLSXEx.php'; + $this->rowsExReader = new SimpleXLSXEx($this); + } + return $this->rowsExReader->readRowsEx($worksheetIndex, $limit); + } + + /** + * Returns cell value + * VERY SLOW! Use ->rows() or ->rowsEx() + * + * @param int $worksheetIndex + * @param string|array $cell ref or coords, D12 or [3,12] + * + * @return mixed Returns NULL if not found + */ + public function getCell($worksheetIndex = 0, $cell = 'A1') + { + + if (($ws = $this->worksheet($worksheetIndex)) === false) { + return false; + } + if (is_array($cell)) { + $cell = $this->_num2name($cell[0]) . $cell[1];// [3,21] -> D21 + } + if (is_string($cell)) { + $result = $ws->sheetData->xpath("row/c[@r='" . $cell . "']"); + if (count($result)) { + return $this->value($result[0]); + } + } + + return null; + } + + protected function _num2name($num) + { + $numeric = ($num - 1) % 26; + $letter = chr(65 + $numeric); + $num2 = (int)(($num - 1) / 26); + if ($num2 > 0) { + return $this->_num2name($num2) . $letter; + } + return $letter; + } + + public function getSheets() + { + return $this->sheets; + } + + public function sheetsCount() + { + return count($this->sheets); + } + + public function sheetName($worksheetIndex) + { + $sn = $this->sheetNames(); + if (isset($sn[$worksheetIndex])) { + return $sn[$worksheetIndex]; + } + + return false; + } + + public function sheetNames() + { + $a = []; + foreach ($this->sheetMetaData as $k => $v) { + $a[$k] = $v['name']; + } + return $a; + } + public function sheetMeta($worksheetIndex = null) + { + if ($worksheetIndex === null) { + return $this->sheetMetaData; + } + return isset($this->sheetMetaData[$worksheetIndex]) ? $this->sheetMetaData[$worksheetIndex] : false; + } + public function isHiddenSheet($worksheetIndex) + { + return isset($this->sheetMetaData[$worksheetIndex]['state']) && $this->sheetMetaData[$worksheetIndex]['state'] === 'hidden'; + } + + public function getStyles() + { + return $this->styles; + } + + public function getPackage() + { + return $this->package; + } + + public function setDateTimeFormat($value) + { + $this->datetimeFormat = is_string($value) ? $value : false; + } +} diff --git a/src/vendors/simplexlsx/src/SimpleXLSXEx.php b/src/vendors/simplexlsx/src/SimpleXLSXEx.php new file mode 100644 index 0000000..27b43b4 --- /dev/null +++ b/src/vendors/simplexlsx/src/SimpleXLSXEx.php @@ -0,0 +1,617 @@ + '000000', + 1 => 'FFFFFF', + 2 => 'FF0000', + 3 => '00FF00', + 4 => '0000FF', + 5 => 'FFFF00', + 6 => 'FF00FF', + 7 => '00FFFF', + 8 => '000000', + 9 => 'FFFFFF', + 10 => 'FF0000', + 11 => '00FF00', + 12 => '0000FF', + 13 => 'FFFF00', + 14 => 'FF00FF', + 15 => '00FFFF', + 16 => '800000', + 17 => '008000', + 18 => '000080', + 19 => '808000', + 20 => '800080', + 21 => '008080', + 22 => 'C0C0C0', + 23 => '808080', + 24 => '9999FF', + 25 => '993366', + 26 => 'FFFFCC', + 27 => 'CCFFFF', + 28 => '660066', + 29 => 'FF8080', + 30 => '0066CC', + 31 => 'CCCCFF', + 32 => '000080', + 33 => 'FF00FF', + 34 => 'FFFF00', + 35 => '00FFFF', + 36 => '800080', + 37 => '800000', + 38 => '008080', + 39 => '0000FF', + 40 => '00CCFF', + 41 => 'CCFFFF', + 42 => 'CCFFCC', + 43 => 'FFFF99', + 44 => '99CCFF', + 45 => 'FF99CC', + 46 => 'CC99FF', + 47 => 'FFCC99', + 48 => '3366FF', + 49 => '33CCCC', + 50 => '99CC00', + 51 => 'FFCC00', + 52 => 'FF9900', + 53 => 'FF6600', + 54 => '666699', + 55 => '969696', + 56 => '003366', + 57 => '339966', + 58 => '003300', + 59 => '333300', + 60 => '993300', + 61 => '993366', + 62 => '333399', + 63 => '333333', + 64 => '000000', // System Foreground + 65 => 'FFFFFF', // System Background' + ]; + public static $CH = [ + 0 => 'ANSI_CHARSET', + 1 => 'DEFAULT_CHARSET', + 2 => 'SYMBOL_CHARSET', + 77 => 'MAC_CHARSET', + 128 => 'SHIFTJIS_CHARSET', + //129 => 'HANGEUL_CHARSET', + 129 => 'HANGUL_CHARSET', + 130 => 'JOHAB_CHARSET', + 134 => 'GB2312_CHARSET', + 136 => 'CHINESEBIG5_CHARSET', + 161 => 'GREEK_CHARSET', + 162 => 'TURKISH_CHARSET', + 163 => 'VIETNAMESE_CHARSET', + 177 => 'HEBREW_CHARSET', + 178 => 'ARABIC_CHARSET', + 186 => 'BALTIC_CHARSET', + 204 => 'RUSSIAN_CHARSET', + 222 => 'THAI_CHARSET', + 238 => 'EASTEUROPE_CHARSET', + 255 => 'OEM_CHARSET' + ]; + public $xlsx; + public $themeColors; + public $fonts; + public $fills; + public $borders; + public $cellStyles; + public $css; + + public function __construct(SimpleXLSX $xlsx) + { + $this->xlsx = $xlsx; + $this->readThemeColors(); + $this->readFonts(); + $this->readFills(); + $this->readBorders(); + $this->readXfs(); + } + public function readThemeColors() + { + $this->themeColors = []; + if (isset($this->xlsx->theme->themeElements->clrScheme)) { + $colors12 = ['lt1', 'dk1', 'lt2', 'dk2','accent1','accent2','accent3','accent4','accent5', + 'accent6','hlink','folHlink']; + foreach ($colors12 as $c) { + $v = $this->xlsx->theme->themeElements->clrScheme->{$c}; + if (isset($v->sysClr)) { + $this->themeColors[] = (string) $v->sysClr['lastClr']; + } elseif (isset($v->srgbClr)) { + $this->themeColors[] = (string) $v->srgbClr['val']; + } else { + $this->themeColors[] = null; + } + } + } + } + + + public function readFonts() + { + // fonts + $this->fonts = []; + if (isset($this->xlsx->styles->fonts->font)) { + foreach ($this->xlsx->styles->fonts->font as $v) { + $u = ''; + if (isset($v->u)) { + $u = isset($v->u['val']) ? (string) $v->u['val'] : 'single'; + } + $f = [ + 'b' => isset($v->b) && ($v->b['val'] === null || $v->b['val']), + 'i' => isset($v->i) && ($v->i['val'] === null || $v->i['val']), + 'u' => $u, + 'strike' => isset($v->strike) && ($v->strike['val'] === null || $v->strike['val']), + 'sz' => isset($v->sz['val']) ? (int) $v->sz['val'] : 11, + 'color' => $this->getColorValue($v->color), + 'name' => isset($v->name['val']) ? (string) $v->name['val'] : 'Calibri', + 'family' => isset($v->family['val']) ? (int) $v->family['val'] : 2, + 'charset' => isset($v->charset['val']) ? (int) $v->charset['val'] : 1, + 'scheme' => isset($v->scheme['val']) ? (string) $v->scheme['val'] : 'minor' + ]; + $this->fonts[] = $f; + } + } + } + public function readFills() + { + // fills + $this->fills = []; + if (isset($this->xlsx->styles->fills->fill)) { + foreach ($this->xlsx->styles->fills->fill as $v) { + if (isset($v->patternFill)) { + $this->fills[] = [ + 'pattern' => isset($v->patternFill['patternType']) ? (string) $v->patternFill['patternType'] : 'none', + 'fgcolor' => $this->getColorValue($v->patternFill->fgColor), + 'bgcolor' => $this->getColorValue($v->patternFill->bgColor) + ]; + } + } + } + } + public function readBorders() + { + $this->borders = []; + if (isset($this->xlsx->styles->borders->border)) { + foreach ($this->xlsx->styles->borders->border as $v) { + $this->borders[] = [ + 'left' => [ + 'style' => (string) $v->left['style'], + 'color' => $this->getColorValue($v->left->color) + ], + 'right' => [ + 'style' => (string) $v->right['style'], + 'color' => $this->getColorValue($v->right->color) + ], + 'top' => [ + 'style' => (string) $v->top['style'], + 'color' => $this->getColorValue($v->top->color) + ], + 'bottom' => [ + 'style' => (string) $v->bottom['style'], + 'color' => $this->getColorValue($v->bottom->color) + ], + 'diagonal' => [ + 'style' => (string) $v->diagonal['style'], + 'color' => $this->getColorValue($v->diagonal->color) + ], + 'horizontal' => [ + 'style' => (string) $v->horizontal['style'], + 'color' => $this->getColorValue($v->horizontal->color) + ], + 'vertical' => [ + 'style' => (string) $v->vertical['style'], + 'color' => $this->getColorValue($v->vertical->color) + ], + 'diagonalUp' => (bool) $v['diagonalUp'], + 'diagonalDown' => (bool) $v['diagonalDown'], + 'outline' => !(isset($v['outline'])) || $v['outline'] + ]; + } + } + } + + public function readXfs() + { + // cellStyles + $this->cellStyles = []; + if (isset($this->xlsx->styles->cellStyleXfs->xf)) { + foreach ($this->xlsx->styles->cellStyleXfs->xf as $v) { + $x = []; + foreach ($v->attributes() as $k1 => $v1) { + $x[ $k1 ] = (int) $v1; + } + if (isset($v->alignment)) { + foreach ($v->alignment->attributes() as $k1 => $v1) { + $x['alignment'][$k1] = (string) $v1; + } + } + $this->cellStyles[] = $x; + } + } + // css + $this->css = []; + // xf + if (isset($this->xlsx->styles->cellXfs->xf)) { + $k = 0; + foreach ($this->xlsx->styles->cellXfs->xf as $v) { + $cf = &$this->xlsx->cellFormats[$k]; + + // alignment + $alignment = []; + if (isset($v->alignment)) { + foreach ($v->alignment->attributes() as $k1 => $v1) { + $alignment[$k1] = (string)$v1; + } + } + + if (isset($cf['xfId'], $this->cellStyles[ $cf['xfId'] ])) { + $s = $this->cellStyles[$cf['xfId']]; + if (!empty($s['applyNumberFormat'])) { + $cf['numFmtId'] = $s['numFmtId']; + } + if (!empty($s['applyFont'])) { + $cf['fontId'] = $s['fontId']; + } + if (!empty($s['applyBorder'])) { + $cf['borderId'] = $s['borderId']; + } + if (!empty($s['applyAlignment'])) { + $alignment = $s['alignment']; + } + } + $cf['alignment'] = $alignment; + + $align = null; + if (isset($alignment['horizontal'])) { + $align = $alignment['horizontal']; + if ($align === 'centerContinuous') { + $align = 'center'; + } + if ($align === 'distributed') { + $align = 'justify'; + } + if ($align === 'general') { + $align = null; + } + } + $cf['align'] = $align; + + $valign = null; + if (isset($alignment['vertical'])) { + $valign = $alignment['vertical']; + if ($valign === 'center' || $valign === 'distributed' || $valign === 'justify') { + $valign = 'middle'; + } + } + $cf['valign'] = $valign; + + // font + if (isset($cf['fontId'])) { + $cf['font'] = $this->fonts[$cf['fontId']]['name']; + $cf['color'] = $this->fonts[$cf['fontId']]['color']; + $cf['f-size'] = $this->fonts[$cf['fontId']]['sz']; + $cf['f-b'] = $this->fonts[$cf['fontId']]['b']; + $cf['f-i'] = $this->fonts[$cf['fontId']]['i']; + $cf['f-u'] = $this->fonts[$cf['fontId']]['u']; + $cf['f-strike'] = $this->fonts[$cf['fontId']]['strike']; + } else { + $cf['font'] = null; + $cf['color'] = null; + $cf['f-size'] = null; + $cf['f-b'] = null; + $cf['f-i'] = null; + $cf['f-u'] = null; + $cf['f-strike'] = null; + } + + // fill + $cf['bgcolor'] = isset($cf['fillId']) ? $this->fills[ $cf['fillId'] ]['fgcolor'] : null; + + // borders + if (isset($cf['borderId'], $this->borders[ $cf['borderId'] ])) { + $border = $this->borders[ $cf['borderId'] ]; + + $borders = ['left', 'right', 'top', 'bottom']; + foreach ($borders as $b) { + $cf['b-' . $b.'-color'] = $border[$b]['color']; + if ($border[$b]['style'] === '' || $border[$b]['style'] === 'none') { + $cf['b-' . $b.'-style'] = ''; + $cf['b-' . $b.'-color'] = ''; + } elseif ($border[$b]['style'] === 'dashDot' + || $border[$b]['style'] === 'dashDotDot' + || $border[$b]['style'] === 'dashed' + ) { + $cf['b-' . $b.'-style'] = 'dashed'; + } else { + $cf['b-' . $b.'-style'] = 'solid'; + } + } + } else { + $cf['b-top-style'] = null; + $cf['b-right-style'] = null; + $cf['b-bottom-style'] = null; + $cf['b-left-style'] = null; + } + + $css = ''; + + if ($cf['color']) { + $css .= 'color: #'.$cf['color'].';'; + } + if ($cf['font']) { + $css .= 'font-family: '.$cf['font'].';'; + } + if ($cf['f-size']) { +// $css .= 'font-size: '.($cf['f-size'] * 0.352806).'mm;'; + $css .= 'font-size: '.(round($cf['f-size'] * 1.3333) + 2).'px;'; + } + if ($cf['f-b']) { + $css .= 'font-weight: bold;'; + } + if ($cf['f-i']) { + $css .= 'font-style: italic;'; + } + if ($cf['f-u']) { + $css .= 'text-decoration: underline;'; + } + if ($cf['f-strike']) { + $css .= 'text-decoration: line-through;'; + } + if ($cf['bgcolor']) { + $css .= 'background-color: #' . $cf['bgcolor'] . ';'; + } + if ($cf['align']) { + $css .= 'text-align: '.$cf['align'].';'; + } + if ($cf['valign']) { + $css .= 'vertical-align: '.$cf['valign'].';'; + } + if ($cf['b-top-style']) { + $css .= 'border-top-style: '.$cf['b-top-style'].';'; + $css .= 'border-top-color: #'.$cf['b-top-color'].';'; + $css .= 'border-top-width: thin;'; + } + if ($cf['b-right-style']) { + $css .= 'border-right-style: '.$cf['b-right-style'].';'; + $css .= 'border-right-color: #'.$cf['b-right-color'].';'; + $css .= 'border-right-width: thin;'; + } + if ($cf['b-bottom-style']) { + $css .= 'border-bottom-style: '.$cf['b-bottom-style'].';'; + $css .= 'border-bottom-color: #'.$cf['b-bottom-color'].';'; + $css .= 'border-bottom-width: thin;'; + } + if ($cf['b-left-style']) { + $css .= 'border-left-style: '.$cf['b-left-style'].';'; + $css .= 'border-left-color: #'.$cf['b-left-color'].';'; + $css .= 'border-left-width: thin;'; + } + $this->css[$k] = $css; + + $k++; + } + } + } + + public function readRowsEx($worksheetIndex = 0, $limit = 0) + { + if (($ws = $this->xlsx->worksheet($worksheetIndex)) === false) { + return; + } + + $dim = $this->xlsx->dimension($worksheetIndex); + $numCols = $dim[0]; + $numRows = $dim[1]; + + /*$emptyRow = array(); + for ($i = 0; $i < $numCols; $i++) { + $emptyRow[] = null; + } + */ + $cols = []; + for ($i = 0; $i < $numCols; $i++) { + $cols[] = ['s' => 0, 'hidden' => false, 'width' => 0]; + } +// $hiddenCols = []; + /* @var SimpleXMLElement $ws */ + if (isset($ws->cols)) { + foreach ($ws->cols->col as $col) { + $min = (int)$col['min']; + $max = (int)$col['max']; + if (($max-$min) > 100) { + $max = $min; + } + for ($i = $min; $i <= $max; $i++) { + $cols[$i-1] = [ + 's' => (int)$col['style'], + 'hidden' => (bool)$col['hidden'], + 'width' => $col['customWidth'] ? (float) $col['width'] : 0 + ]; + } + } + } + + $curR = 0; + $_limit = $limit; + + foreach ($ws->sheetData->row as $row) { + $curC = 0; + + $r_idx = (int)$row['r']; + $r_style = ['s' => 0, 'hidden' => (bool)$row['hidden'], 'height' => 0]; + if ($row['customFormat']) { + $r_style['s'] = (int)$row['s']; + } + if ($row['customHeight']) { + $r_style['height'] = (int)$row['ht']; + } + + $cells = []; + for ($i = 0; $i < $numCols; $i++) { + $cells[] = null; + } + + foreach ($row->c as $c) { + $r = (string)$c['r']; + $t = (string)$c['t']; + $s = (int)$c['s']; + + $idx = $this->xlsx->getIndex($r); + $x = $idx[0]; + $y = $idx[1]; + + if ($x > -1) { + $curC = $x; + if ($curC >= $numCols) { + $numCols = $curC + 1; + } + while ($curR < $y) { + $emptyRow = []; + for ($i = 0; $i < $numCols; $i++) { + $emptyRow[] = $this->valueEx($cols[$i], $i, $curR); + } + yield $emptyRow; + $curR++; + + $_limit--; + if ($_limit === 0) { + return; + } + } + } + $data = [ + 'type' => $t, + 'name' => $r, + 'value' => $this->xlsx->value($c), + 'href' => $this->xlsx->href($worksheetIndex, $c), + 'f' => (string)$c->f, + 'r' => $r_idx, + 's' => ($s > 0) ? $s : $cols[$curC]['s'], + 'hidden' => $r_style['hidden'] || $cols[$curC]['hidden'], + 'width' => $cols[$curC]['width'], + 'height' => $r_style['height'] + ]; + $cells[$curC] = $this->valueEx($data, $curC, $curR); + + $curC++; + } + // check empty cells + for ($i = 0; $i < $numCols; $i++) { + if ($cells[$i] === null) { + if ($r_style['s'] > 0) { + $data = $r_style; + } else { + $data = $cols[$i]; + } + $data['width'] = $cols[$i]['width']; + $data['height'] = $r_style['height']; + $cells[$i] = $this->valueEx($data, $i, $curR); + } + } + + yield $cells; + + $curR++; + $_limit--; + if ($_limit === 0) { + break; + } + } + + while ($curR < $numRows) { + $emptyRow = []; + for ($i = 0; $i < $numCols; $i++) { + $data = $cols[$i]; + $emptyRow[] = $this->valueEx($data, $i, $curR); + } + yield $emptyRow; + $curR++; + $_limit--; + if ($_limit === 0) { + return; + } + } + } + + protected function valueEx($data, $x = null, $y = null) + { + + $r = [ + 'type' => '', + 'name' => '', + 'value' => '', + 'href' => '', + 'f' => '', + 'format' => '', + 's' => 0, + 'css' => '', + 'r' => '', + 'hidden' => false, + 'width' => 0, + 'height' => 0 + ]; + foreach ($data as $k => $v) { + if (isset($r[$k])) { + $r[$k] = $v; + } + } + $st = &$this->xlsx->cellFormats[$r['s']]; + $r['format'] = $st['format']; + $r['css'] = &$this->css[ $r['s'] ]; + if ($r['value'] !== '' && !$st['align'] && !in_array($r['type'], ['s','str','inlineStr','e'], true)) { + $r['css'] .= 'text-align: right;'; + } + + if (!$r['name']) { + $c = ''; + for ($k = $x; $k >= 0; $k = (int)($k / 26) - 1) { + $c = chr($k % 26 + 65) . $c; + } + $r['name'] = $c . ($y + 1); + $r['r'] = $y+1; + } + return $r; + } + public function getColorValue(SimpleXMLElement $a = null, $default = '') + { + if ($a === null) { + return $default; + } + $c = $default; // auto + if ($a['rgb'] !== null) { + $c = substr((string) $a['rgb'], 2); // FFCCBBAA -> CCBBAA + } elseif ($a['indexed'] !== null && isset(static::$IC[ (int) $a['indexed'] ])) { + $c = static::$IC[ (int) $a['indexed'] ]; + } elseif ($a['theme'] !== null && isset($this->themeColors[ (int) $a['theme'] ])) { + $c = $this->themeColors[ (int) $a['theme'] ]; + } + if ($a['tint'] !== null) { + list($r,$g,$b) = array_map('hexdec', str_split($c, 2)); + $tint = (float) $a['tint']; + if ($tint > 0) { + $r += (255 - $r) * $tint; + $g += (255 - $g) * $tint; + $b += (255 - $b) * $tint; + } else { + $r += $r * $tint; + $g += $g * $tint; + $b += $b * $tint; + } + $c = strtoupper( + str_pad(dechex((int) $r), 2, '0', 0) . + str_pad(dechex((int) $g), 2, '0', 0) . + str_pad(dechex((int) $b), 2, '0', 0) + ); + } + return $c; + } +}