Ir para conteúdo
kania

Função genérica para atualizar chave em JSON duplicada usando o PHP

Recommended Posts

Tenho a seguinte situação.
Recebo vários JSONs podendo ou não ser multidimensional, preciso atualizar uma determinada chave deste JSON, o problema é que algumas chaves podem ser duplicadas, bem como seus respectivos valores. Como estou tentando criar uma função genérica para navegar em qualquer JSON e modificar a chave em si, com estas duplicidades de chaves, estou tendo dificuldades em dizer ao código qual é chave que devo alterar.

 

Arquivo JSON Exemplo

 

{
      "CREDITOR": {
        "TAX": {
          "TAC": 0.7
        },
        "ENABLE": "true",
        "PRODUCTION": {
          "email": "email@dominio.com",
          "senha": "12457895",
          "BASE_URL": "https://domino.com"
        },
        "HOMOLOGATION": {
          "email": "email@dominio.com",
          "senha": "12457895",
          "BASE_URL": "https://domino.com"
        },
        "TARGET_VALUES": 5000000
      }
    }

 

Converto o JSON para array

 

$json = json_decode($json_string, true);


Função que criei até aqui

 

   

/**
     * Encontra a chave correspondente dentro do JSON
     *
     * @param array $jsonArray - JSON a ser verificado
     * @param string $keyFather - chave de entrada
     * @param string $keyUpdate - chave que modificar
     * @param string $valueUpdate - novo valor da chave
     * @return string
     *
     */
    public static function searchKeyJson(array $jsonArray, string $keyFather, string $keyUpdate = null, $valueUpdate = null)
    {
        foreach ($jsonArray as $key => $value) {
            if ($key == $keyFather && $keyUpdate == null) {
                $jsonArray[$key] =  $valueUpdate;
                return $jsonArray;
            }
            if ($key == $keyFather && $keyUpdate != null) {
                $jsonArray[$keyFather][$keyUpdate] = $valueUpdate;
                return $jsonArray;
            }
            if (is_array($value)) {
                if (($result = self::searchKeyJson($value, $keyFather, $keyUpdate, $valueUpdate)) !== false) {
                    if ($keyUpdate == null) {
                        return $result;
                    } else {
                        return $result;
                    }
                }
            }
        }
        return false;
    }


Até modifico o valor, mais no final para salvar, ele não monta o JSON como original, ele caba ignorando a chave inicial no JSON de exmeplo "CREDITOR": {}

 

Retorno da função (notem que esta forma do padrão da original)

 

=> [
         "TAX" => [
           "TAC" => 0.7,
         ],
         "ENABLE" => "true",
         "PRODUCTION" => [
           "email" => "teste",
           "senha" => "12457895",
           "BASE_URL" => "https://domino.com",
         ],
         "HOMOLOGATION" => [
           "email" => "email@dominio.com",
           "senha" => "12457895",
           "BASE_URL" => "https://domino.com",
         ],
         "TARGET_VALUES" => 5000000,
       ]

 

Se eu percorrer o array e tentar modificar a chave em questão, ele muda todas as as chaves que tiverem no JSON porque tem duplicidade.

Como posso resolver isto com uma função global que sirva para qualquer padrão de JSON que eu tiver?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Olá amigo, tudo bem?

 

Vou tentar ajudar você, mas não entendi alguns pontos:

 

No seu exemplo houve alteração no e-mail apenas de PRODUCTION, mas não em HOMOLOGATION. É esse o comportamento esperado?

Desculpe, mas não entendi muito bem seu objetivo: seria varrer todo o array pela chave 'email' (por exemplo) e substituir todas as ocorrências ou apenas a primeira encontrada (ou ainda outra coisa)?

 

Apenas para ilustrar melhor, como você fez a chamada da sua função para que ela gerasse o resultado que você colou no seu post? Digo, quais parâmetros você passou pra dentro dela?

 

Apenas uma observação:

                    if ($keyUpdate == null) {
                        return $result;
                    } else {
                        return $result;
                    }

É o mesmo que simplesmente:

return $result;

(Provavelmente foi apenas falta de atenção, mas não custa mencionar...)

Compartilhar este post


Link para o post
Compartilhar em outros sites

Olá noite Mateus, obrigado por responder.

 

A citação do erro estava correta, dupliquei o retorno do return $result (hehehe)

 

Vamos lá, vou detalhar melhor o que estou tentando fazer.

 

A aplicação Backend esta em uma API em Laravel 9, com banco de dados Mysql e o Front em Vue.js 3.

No banco de dados, existem várias tabelas com colunas do tipo jsonb.

 

O que preciso fazer é manipular este campo jsonb no PHP, para isto pensei no seguinte.

 

- Ter uma função genérica já que estes campos jsonb não tem um json igual em cada;

- A função precisa poder percorrer o json (já convertido em array para trabalhar no php) e encontrara chave especifica para poder modifica-la

 

No exemplo acima, eu cheguei a conseguir modificar a chave email da chave pai PRODUCTION efetuando chamada

searchKeyJson($jsonArray, , , "VALOR MODIFICADO")

Sendo que o parâmetro $keyUpdate é facultativo, já que posso precisar alterar um chave que esta em primeiro nível no json.

 

Funcionou a modificação para este exemplo de json/array, mais não funciona em todos os casos, pois como monto as chaves na $jsonArray[$keyFather][$keyUpdate] = $valueUpdate; ele se perde quando não encontra as referencias conforme a profundidade do array.


A ideia inicial era que eu pudesse passar apenas a chave em si que quero manipular (exemplo: email), mais não funcionaria porque como no json do exemplo, eu tenho duas chaves e-mail, uma no PRODUCTION e outra no HOMOLOGATION, logo ou vai modificar todas as chaves, ou vai modificar apenas a primeira que encontrar.

 

Ai estou pesquisando para ver como posso resolver este pepinão (hehehe), tendo em vista que estes campos jsonb do banco tem configuração do sistema importantes que precisam ser manipulados em um front, não da para ficar ajustando eles não mão sempre que precisar.

 

Exemplo da Função completa ate o momento, com 2 json e duas chamadas para testar, ambas funcionam, porem como mencionei, dependendo da profundidade da chave não consegue fazer a atualização.

 

<?php

// $json_string = '{"COMISSAO":{"EXTRA":0.5,"AGENTE":0.5,"ESCRITORIO":1},"PROPOSTA":{"API":[4,5,6,7,8,9,10,11],"JUROS":[1,2],"PRAZO":[1,2,3,4],"MAX_JUROS":2}}';

$json_string = '{"CREDITOR":{"TAX":{"TAC":0.7},"ENABLE":"true","PRODUCTION":{"email":"email@dominio.com","senha":"12457895","BASE_URL":"https://domino.com"},"HOMOLOGATION":{"email":"email@dominio.com","senha":"12457895","BASE_URL":"https://domino.com"},"TARGET_VALUES":5000000}}';

$json = json_decode($json_string, true);

function searchKeyJson(array &$jsonArray, string $keyFather, string $keyUpdate = null, $valueUpdate = null)
{
    foreach ($jsonArray as $key => $value) {
        if ($key == $keyFather && $keyUpdate == null) {
            $jsonArray[$key] =  $valueUpdate;
            return $jsonArray;
        }
        if ($key == $keyFather && $keyUpdate != null) {
            $jsonArray[$keyFather][$keyUpdate] =  $valueUpdate;
            return $jsonArray;
        }
        if (is_array($value)) {
            if (($result = searchKeyJson($jsonArray[$key], $keyFather, $keyUpdate, $valueUpdate)) !== false) {
                return $jsonArray;
            }
        }
    }
    return false;
}

// Chamada da função sem passar a chave de resultado
$returnWithoutKey = searchKeyJson($json, "PRODUCTION", "email", "TESTE UPDATE");
// $returnWithoutKey = searchKeyJson($json, "PROPOSTA", "API", [1,2,5,8]);

// Exemplo de valor a ser modificado dentro do JSON
echo "RETORNO".PHP_EOL;
echo "========================".PHP_EOL;
print_r($returnWithoutKey);


?>

 

Editado por kania
Adição de conteúdo necessário

Compartilhar este post


Link para o post
Compartilhar em outros sites

Certo, acho que agora entendi melhor, mas infelizmente acredito que essa necessidade seja oriunda de um modelo de dados que poderia ser otimizado no futuro.

 

Dito isso, elaborei uma pequena solução que espero que lhe ajude. Veja:

 

1 - Primeiro pegamos o caminho até o subarray desejado:

function getSubArrayPath( $array, $wantedKey ) {
    $mode = RecursiveIteratorIterator::SELF_FIRST;
    $iterator = new RecursiveIteratorIterator( new RecursiveArrayIterator( $array ), $mode );
    
    foreach ( $iterator as $key => $value )
        if ( $wantedKey === $key ) {
            $keys[] = $key;
            for ( $i = $iterator->getDepth()-1; $i >= 0 ; --$i ) {
                $keys[] = $iterator->getSubIterator( $i )->key();
            }
            
            return $keys;
        }
    
    return [];
}

Essa função, que faz uso das classes nativas RecursiveIteratorIterator e RecursiveArrayIterator tem a simples tarefa de receber um array (como o que o json_decode nos entregou) e dizer qual o caminho deve ser feito para chegarmos até a chave desejada (no caso PRODUCTION).

Ela deve se comportar da seguinte maneira:

$path = getSubArrayPath( $array, $key );

Retorna isso:
Array
(
    [0] => PRODUCTION
    [1] => CREDITOR
)

 

 

2 - Agora que temos o caminho dinâmico que estava enraizado na nossa árvore de dados, podemos encontrar a referência do subarray que queremos manipular. Para isso criamos a seguinte função:

function &getSubArrayRef( &$array, $key ) {
    $path = getSubArrayPath( $array, $key );
    $ref =& $array;
    
    while ( $node = array_pop( $path ) )
        $ref =& $ref[ $node ];
    
    return $ref;
}

Essa função é simples: enviamos os dados e dizemos a chave que ela deve encontrar recursivamente. Ela vai internamente chamar a "getSubArrayPath()" para determinar o caminho e então retornar a referência do subarray que desejamos.

 

 

Se reunirmos tudo teríamos esse código:

<?php
$json = '{"CREDITOR":{"TAX":{"TAC":0.7},"ENABLE":"true","PRODUCTION":{"email":"email@dominio.com","senha":"12457895","BASE_URL":"https://domino.com"},"HOMOLOGATION":{"email":"email@dominio.com","senha":"12457895","BASE_URL":"https://domino.com"},"TARGET_VALUES":5000000}}';
$data = json_decode( $json, true );

function getSubArrayPath( $array, $wantedKey ) {
    $mode = RecursiveIteratorIterator::SELF_FIRST;
    $iterator = new RecursiveIteratorIterator( new RecursiveArrayIterator( $array ), $mode );
    
    foreach ( $iterator as $key => $value )
        if ( $wantedKey === $key ) {
            $keys[] = $key;
            for ( $i = $iterator->getDepth()-1; $i >= 0 ; --$i ) {
                $keys[] = $iterator->getSubIterator( $i )->key();
            }
            
            return $keys;
        }
    
    return [];
}

function &getSubArrayRef( &$array, $key ) {
    $path = getSubArrayPath( $array, $key );
    $ref =& $array;
    
    while ( $node = array_pop( $path ) )
        $ref =& $ref[ $node ];
    
    return $ref;
}

$ref = &getSubArrayRef( $data, 'PRODUCTION' );
$ref[ 'email' ] = 'novo e-mail';
$ref[ 'senha' ] = 'nova senha';
$ref[ 'atributo_novo' ] = 'AAAAAAAAAA';

print_r( $data );

 

E o retorno disso seria esse:

Array
(
    [CREDITOR] => Array
        (
            [TAX] => Array
                (
                    [TAC] => 0.7
                )

            [ENABLE] => true
            [PRODUCTION] => Array
                (
                    [email] => novo e-mail
                    [senha] => nova senha
                    [BASE_URL] => https://domino.com
                    [atributo_novo] => AAAAAAAAAA
                )

            [HOMOLOGATION] => Array
                (
                    [email] => email@dominio.com
                    [senha] => 12457895
                    [BASE_URL] => https://domino.com
                )

            [TARGET_VALUES] => 5000000
        )

)

 

Achei melhor dividir as responsabilidades e trazer as manipulações para fora da função, mas se você preferir fazer tudo numa chamada só, basta modificar o valor de $ref após o while da nossa função "getSubArrayRef()". Dessa forma você poderia enviar o valor desejado e já sair com o array modificado de dentro da função (como você estava fazendo antes).

Compartilhar este post


Link para o post
Compartilhar em outros sites

Olá Matheus, tudo bom?

Bacana sua ideia, funciona bem quando passamos bem definida as referencias, mais acaba no mesmo problema que eu ainda não consegui resolver, a função não fica genérica para tratar qualquer json passando um parent como referencia para alterar um children.

 

Por exemplo, vamos dizer que o mesmo json foi modificado em algum momento e agora preciso modificar a chave TAC, eu precisaria passar como paramento principal a chave TESTE ou CREDITOR, e nas referencias todas as chaves em cadeia para modificar o item correto, isto? Estou tentando facilitar a vida do Front em não ter que passar todas estas referencias para a API, mais não sei se tem como.

 

$ref = &getSubArrayRef( $data, 'TESTE' );
$ref[ 'TAX' ]['TAC'] = 'nova tac';

 

JSON MODIFICADO COM A CHAVE [TESTE]

{
  "TESTE": {
    "TAX": {
      "TAC": 0.7
    }
  },
  "CREDITOR": {
    "TAX": {
      "TAC": 0.7
    },
    "ENABLE": "true",
    "PRODUCTION": {
      "email": "TESTE 5 tregbg",
      "senha": "aL1VM8Z6qYsc",
      "BASE_URL": "https://api.bancarizaao.fiduciascm.digital/"
    },
    "HOMOLOGATION": {
      "email": "integracao@selectinvestimentos.com",
      "senha": "1234",
      "BASE_URL": "https://api.americanohoml.fiduciascm.digital/"
    },
    "TARGET_VALUES": 5000000
  }
}

 

Outra opção que estou vendo se seria viável é usar spred operator, ai o front continuaria tendo que passar as referencia de toda  a arvore que vai ter que ser modificada, contudo só passaria um lista de string, mais ainda não testei para ver se ficaria viável.

 

function teste(...$param){
    foreach($param as $key => $val){
        echo '["'.$val.'"]';
    }
}

return teste("CREDITOR", "PRODUCTION", "email");

 

Compartilhar este post


Link para o post
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisar ser um membro para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar Agora

  • Conteúdo Similar

    • Por violin101
      Caros amigos, saudações.
       
      Estou com uma dúvida de validação de INPUT com função moeda.
       
      Tenho um input onde o usuário digita um valor qualquer, por exemplo: 1.234,56
      o problema é quando precisa atualizar o valor.
       
      Quando o usuário atualizar o input fica assim: 1.234,
       
      como faço para atualizar as casas decimais, conforme o valor for sendo alterado ?
       
      o input está assim:
       
      <div class="col-md-2"> <label for="">Valor Unitário</label> <input type="text" class="form-control" id="estoqprod" name="estoqprod" style="font-size:15px; font-weight:bold; width:100%; text-align:center;" placeholder="0,00" OnKeyUp="calcProd();" onkeypress="return(FormataMoeda(this,'.',',',event))" > </div>  
      a função para formatar o input para moeda está assim:
      obs.: a Função CalcProd está executando corretamente
      function calcProd(){ //Obter valor digitado do produto var estoq_prod = document.getElementById("estoqprod").value; //Remover ponto e trocar a virgula por ponto while (estoq_prod.indexOf(".") >= 0) { estoq_prod = estoq_prod.replace(".", ""); } estoq_prod = estoq_prod.replace(",","."); //Obter valor digitado do produto var prod_qtde = document.getElementById("qtde").value; //Remover ponto e trocar a virgula por ponto while (prod_qtde.indexOf(".") >= 0) { prod_qtde = prod_qtde.replace(".", ""); } prod_qtde = prod_qtde.replace(",","."); //Calcula o Valor do Desconto if (prod_qtde > 0 && estoq_prod > 0) { calc_total_produto = parseFloat(prod_qtde) - parseFloat(estoq_prod); var numero = calc_total_produto.toFixed(2).split('.'); //Calculo para não deixar GRAVAR valores negativos if (calc_total_produto < 0 ) { numero[0] = numero[0].split(/(?=(?:...)*$)/).join('.') * -1; document.getElementById("qtdeTotal").value = numero.join(','); } else { numero[0] = numero[0].split(/(?=(?:...)*$)/).join('.'); document.getElementById("qtdeTotal").value = numero.join(','); } } else { if (estoq_prod > 0) { document.getElementById("qtdeTotal").value = document.getElementById("estoqprod").value; } else { document.getElementById("qtdeTotal").value = "0,00"; } } } /*---Função para Formatar Campo para Moeda [R$]---*/ function FormataMoeda(objTextBox, SeparadorMilesimo, SeparadorDecimal, e){ var sep = 0; var key = ''; var i = j = 0; var len = len2 = 0; var strCheck = '0123456789'; var aux = aux2 = ''; var whichCode = (window.Event) ? e.which : e.keyCode; if (whichCode == 13) return true; key = String.fromCharCode(whichCode); // Valor para o código da Chave if (strCheck.indexOf(key) == -1) return false; // Chave inválida len = objTextBox.value.length; for(i = 0; i < len; i++) if ((objTextBox.value.charAt(i) != '0') && (objTextBox.value.charAt(i) != SeparadorDecimal)) break; aux = ''; for(; i < len; i++) if (strCheck.indexOf(objTextBox.value.charAt(i))!=-1) aux += objTextBox.value.charAt(i); aux += key; len = aux.length; if (len == 0) objTextBox.value = ''; if (len == 1) objTextBox.value = '0'+ SeparadorDecimal + '0' + aux; if (len == 2) objTextBox.value = '0'+ SeparadorDecimal + aux; if (len > 2) { aux2 = ''; for (j = 0, i = len - 3; i >= 0; i--) { if (j == 3) { aux2 += SeparadorMilesimo; j = 0; } aux2 += aux.charAt(i); j++; } objTextBox.value = ''; len2 = aux2.length; for (i = len2 - 1; i >= 0; i--) objTextBox.value += aux2.charAt(i); objTextBox.value += SeparadorDecimal + aux.substr(len - 2, len); } return false; }  
      Grato,
       
      Cesar
    • Por violin101
      Caros amigos, saudações.
       
      Estou com uma dúvida de validação de INPUT com função moeda.
       
      Tenho um input onde o usuário digita um valor qualquer, por exemplo: 1.234,56
      o problema é quando precisa atualizar o valor.
       
      Quando o usuário atualizar o input fica assim: 1.234,
       
      como faço para atualizar as casas decimais, conforme o valor for sendo alterado ?
       
      o input está assim:
       
      <div class="col-md-2"> <label for="">Valor Unitário</label> <input type="text" class="form-control" id="estoqprod" name="estoqprod" style="font-size:15px; font-weight:bold; width:100%; text-align:center;" placeholder="0,00" OnKeyUp="calcProd();" onkeypress="return(FormataMoeda(this,'.',',',event))" > </div>  
      a função para formatar o input para moeda está assim:
      obs.: a Função CalcProd está executando corretamente
      function calcProd(){ //Obter valor digitado do produto var estoq_prod = document.getElementById("estoqprod").value; //Remover ponto e trocar a virgula por ponto while (estoq_prod.indexOf(".") >= 0) { estoq_prod = estoq_prod.replace(".", ""); } estoq_prod = estoq_prod.replace(",","."); //Obter valor digitado do produto var prod_qtde = document.getElementById("qtde").value; //Remover ponto e trocar a virgula por ponto while (prod_qtde.indexOf(".") >= 0) { prod_qtde = prod_qtde.replace(".", ""); } prod_qtde = prod_qtde.replace(",","."); //Calcula o Valor do Desconto if (prod_qtde > 0 && estoq_prod > 0) { calc_total_produto = parseFloat(prod_qtde) - parseFloat(estoq_prod); var numero = calc_total_produto.toFixed(2).split('.'); //Calculo para não deixar GRAVAR valores negativos if (calc_total_produto < 0 ) { numero[0] = numero[0].split(/(?=(?:...)*$)/).join('.') * -1; document.getElementById("qtdeTotal").value = numero.join(','); } else { numero[0] = numero[0].split(/(?=(?:...)*$)/).join('.'); document.getElementById("qtdeTotal").value = numero.join(','); } } else { if (estoq_prod > 0) { document.getElementById("qtdeTotal").value = document.getElementById("estoqprod").value; } else { document.getElementById("qtdeTotal").value = "0,00"; } } } /*---Função para Formatar Campo para Moeda [R$]---*/ function FormataMoeda(objTextBox, SeparadorMilesimo, SeparadorDecimal, e){ var sep = 0; var key = ''; var i = j = 0; var len = len2 = 0; var strCheck = '0123456789'; var aux = aux2 = ''; var whichCode = (window.Event) ? e.which : e.keyCode; if (whichCode == 13) return true; key = String.fromCharCode(whichCode); // Valor para o código da Chave if (strCheck.indexOf(key) == -1) return false; // Chave inválida len = objTextBox.value.length; for(i = 0; i < len; i++) if ((objTextBox.value.charAt(i) != '0') && (objTextBox.value.charAt(i) != SeparadorDecimal)) break; aux = ''; for(; i < len; i++) if (strCheck.indexOf(objTextBox.value.charAt(i))!=-1) aux += objTextBox.value.charAt(i); aux += key; len = aux.length; if (len == 0) objTextBox.value = ''; if (len == 1) objTextBox.value = '0'+ SeparadorDecimal + '0' + aux; if (len == 2) objTextBox.value = '0'+ SeparadorDecimal + aux; if (len > 2) { aux2 = ''; for (j = 0, i = len - 3; i >= 0; i--) { if (j == 3) { aux2 += SeparadorMilesimo; j = 0; } aux2 += aux.charAt(i); j++; } objTextBox.value = ''; len2 = aux2.length; for (i = len2 - 1; i >= 0; i--) objTextBox.value += aux2.charAt(i); objTextBox.value += SeparadorDecimal + aux.substr(len - 2, len); } return false; }  
      Grato,
       
      Cesar
    • Por violin101
      Caros amigos, saudações.
       
      Desculpa postar minha dúvida, fiz várias pesquisa mas não tive sucesso.
       
      Como faço para capturar o ID do SELECT selecionado e passar para base_url ?
       
      Exemplo:
      após selecionar o ID passar para <?php echo base_url();?>estoque/ajuste/adicionar/ <== passar o ID aqui.
       
      <div class="col-md-6"> <label for="tipoDepart" class="control-label">Departamento:</label> <select name="tipoDepart" id="tipoDepart" style="width:100%;" class="form-control"> <option value="">Selecione um Departamento</option> <?php foreach ($dprts as $dp) { echo '<option value="'.$dp->idDepartamento.'">'.$dp->departamento.'</option>'; } ?> </select> </div> <div class="col-md-6"> <div class="card card-entrad"> <div class="card-header"> <label class="card-tlentr">Entrada - Estoque</label> </div> <div class="card-body"> <div style="text-align:center;"> <a href="<?php echo base_url();?>estoque/ajuste/adicionar/" <== COMO PASSO O ID SELECIONADO AQUI, PARA ABRIR A PÁGINA COM O ID DO DPTO ? class="btn btn-cinza">Adicionar</a> </div> </div> </div> </div>  
      Observação: preciso capturar e passar o ID para gerar TABELA referente a cada departamento.
       
      Grato,
       
      Cesar
    • Por violin101
      Caros amigos, saudações.
       
      Tem como passar para o Formulário um Campo vindo via AJAX no formato moeda ?
       
      Tenho uma rotina onde o usuário escolhe através de uma Lista na modal de Produtos e o sistema informa o formulário os seguintes campos:
      código | descrição | espécie | estoque atual.
       
      o estoque atual preciso passar nesse formato, para validação de quantidade: 15.00 ou 15,00.
      ou seja:
      converter de: 15 
      para: 15.00 com casas decimais

      tem como fazer isso ?
       
      Grato,
       
      Cesar
    • Por violin101
      Caros amigos, saudações.
       
      Tem como passar para o Formulário um Campo vindo via AJAX no formato moeda ?
       
      Tenho uma rotina onde o usuário escolhe através de uma Lista na modal de Produtos e o sistema informa o formulário os seguintes campos:
      código | descrição | espécie | estoque atual.
       
      o estoque atual preciso passar nesse formato, para validação de quantidade: 15.00 ou 15,00.

      tem como fazer isso ?
       
      Grato,
       
      Cesar
×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.