Teste de PI

Tudo aquilo que tens de saber para tirar um 20 a PI.

Exemplos

Formulário

include/config.inc.php

<?php
@session_start();

if ($_SERVER["HTTP_HOST"] == "localhost") {
  $site_url = 'http://localhost/projeto002/';
  $site_dir = 'C:/wamp64/www/projeto002/';
} else {
  $site_url = 'http://web.colgaia.local/12itm212/projeto002/';
  $site_dir = 'C:/Share/12itm212/www/projeto002/';
}

$escolas = array(
  "Escola 1",
  "Escola 2",
  "Escola 3",
);
?>

index.php

<?php
  include 'include/config.inc.php';
?>
<!DOCTYPE html>
<html lang="pt">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@picocss/pico@1/css/pico.min.css">
    <title>Formulário</title>
    <style>
        .red {
            color: red;
        }
    </style>
</head>

<body>
  <main class="container">
    <h1>
        Formulário
    </h1>
    <form
      action="trata-form.php"
      method="post"
      enctype="multipart/form-data"
      onsubmit="return validateForm()"
    >
      <label for="escola">Escola <span class="red">(*)</span>:</label>
      <select name="escola" id="escola" required>
        <option value="" disabled selected>Escolhe uma escola</option>
        <?php
        foreach ($escolas as $escola) {
            echo "<option value='$escola'>$escola</option>";
        }
        ?>
      </select><br>

      <label for="nome">Nome <span class="red">(*)</span>:</label>
      <input type="text" name="nome" id="nome" required><br>

      <label for="fotografia">Fotografia <span class="red">(*)</span>:</label>
      <input type="file" name="fotografia" id="fotografia" accept="image/*" required><br>

      <label for="data_nascimento">Data de Nascimento <span class="red">(*)</span>:</label>
      <input type="date" name="data_nascimento" id="data_nascimento" required><br>

      <input type="submit" value="Enviar">Enviar</input>
    </form>
  </main>

  <script>
    function validateForm() {
      const formData = new FormData(document.querySelector('form'));

      if (!formData.has("algo")) {
          alert('Todos os campos são obrigatórios.');
          return false;
      }

      if (getAge(dataNascimento) < 5) {
          alert('A data de nascimento deve ser maior que 5 anos.');
          return false;
      }

      return true;
    }

    function getAge(birthDateString) {
      let today = new Date();
      let birthDate = new Date(birthDateString);
      let age = today.getFullYear() - birthDate.getFullYear();
      let m = today.getMonth() - birthDate.getMonth();
      if (m < 0 || (m === 0 && today.getDate() < birthDate.getDate())) {
          age--;
      }
      return age;
    }
  </script>
</body>
</html>

trata-form.php

<?php
include 'include/config.inc.php';

if ($_SERVER["REQUEST_METHOD"] != "POST") {
  header("Location: error.php?msg=InvalidRequestMethod");
  exit();
}

extract($_POST, EXTR_PREFIX_ALL, 'form');

if (empty($escola) || empty($nome) || empty($email) || empty($dataNascimento) || empty($nif)) {
  header("Location: error.php?msg=MissingFields");
  exit();
}

if (!validateNIF($nif)) {
  header("Location: error.php?msg=InvalidNIF");
  exit();
}

if (new DateTime('-5 years') < new DateTime($dataNascimento)) {
  header("Location: error.php?msg=InvalidAge");
  exit();
}

$fotografia = $_FILES['fotografia'];

if ($fotografia['error'] != 0) {
  header("Location: error.php?msg=UploadError");
  exit();
}

$allowed_types = ['image/jpeg', 'image/png'];
$max_size = 5 * 1024 * 1024; // 5 MB

if (!in_array($fotografia['type'], $allowed_types) || $fotografia['size'] > $max_size) {
  header("Location: error.php?msg=InvalidImage");
  exit();
}

$target_folder = "uploads/";
$target_path = $target_folder . time() . '_' . $fotografia['name'];
move_uploaded_file($fotografia['tmp_name'], $site_dir . $target_path);

$query_string = http_build_query($_POST + ['fotografia' => $target_path]);

header("Location: success.php?$query_string");
exit();
?>

error.php

<?php
include 'include/config.inc.php';

$error_messages = [
  'InvalidImage' => 'A imagem é inválida. Certifique-se de que é do tipo JPEG ou PNG e tem no máximo 5 MB.',
  'UploadError' => 'Ocorreu um erro ao carregar a imagem. Tente novamente mais tarde.',
  'InvalidNIF' => 'O NIF inserido é inválido. Certifique-se de que possui 9 dígitos válidos.',
  'MissingFields' => 'Todos os campos são obrigatórios. Preencha todos os campos e tente novamente.',
  'InvalidRequestMethod' => 'Método de requisição inválido. Volte ao formulário e submeta novamente.',
  'UnknownError' => 'Ocorreu um erro desconhecido. Tente novamente mais tarde.',
  'InvalidAge' => 'A data de nascimento deve ser maior que 5 anos. Tente novamente mais tarde.'
];

$msg = isset($_GET['msg']) ? $_GET['msg'] : 'UnknownError';

$error_message = $error_messages[$msg];

?>

<!DOCTYPE html>
<html lang="pt">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@picocss/pico@1/css/pico.min.css">
  <title>Erro</title>
</head>

<body>
  <main class="container">
    <h1>
      Erro
    </h1>
    <p>
      <?php echo $error_message; ?>
    </p>
    <a href="<?php echo $site_url ?>">Tentar Novamente</a>
  </main>
</body>
</html>

Traduções

include/config.inc.php

<?php
@session_start();

$arrIdiomas = array("pt" => "Português", "en" => "English", "es" => "Español", "ru" => "Русский");

if (!isset($_COOKIE['idioma'])) {
  setcookie('idioma', 'pt', time() + (84600 * 30), '/');
  $_SESSION['idioma'] = 'pt';
} else {
  if (!isset($_SESSION['idioma']))
    $_SESSION['idioma'] = $_COOKIE['idioma'];
}

$site_url = 'http://web.colgaia.local/12itm212/projeto001';
$site_dir = 'C:/Share/12itm212/www/projeto001';

$lang_dir = $site_dir . '/include/lang/' . $_SESSION['idioma'] . '.inc.php';
include $lang_dir;

?>

include/lang/[lang].inc.php

<?php
$arrTexto['titulo'] = 'Título';
$arrTexto['subtitulo'] = 'Subtítulo';
?>

includes/navbar.inc.php

<?php
  $rotaTotal = explode("/", $_SERVER['SCRIPT_NAME']);
  $rotaAtual = $rotaTotal[count($rotaTotal) - 1];

  $rotas = array(
    "index.php" => $arrTexto["homepage"],
    "sobre.php" => $arrTexto["sobre"],
    "filmes.php" => $arrTexto["lista-filmes"],
    "series.php" => $arrTexto["lista-series"],
    "contacto.php" => $arrTexto["contacto"],
  );
?>

<section class="menu">
  <h2>
    <?php
      echo $arrTexto['menu']
    ?>
  </h2>
  <nav>
    <ul>
      <?php
        foreach ($rotas as $rota => $nomeRota) {
          $ativo = "";
          if ($rotaAtual == $rota) {
            $ativo = 'class="current-page"';
          }
          echo "<li><a href=\"$rota\" $ativo>$nomeRota</a></li>";
        }
      ?>
    </ul>
  </nav>
</section>

Código Útil

JavaScript

validateNIF

function validateNIF(value) {
  const nif = typeof value === 'string' ? value : value.toString();
  const validationSets = {
    one: ['1', '2', '3', '5', '6', '8'],
    two: ['45', '70', '71', '72', '74', '75', '77', '79', '90', '91', '98', '99']
  };
  if (nif.length !== 9) return false;
  if (!validationSets.one.includes(nif.substr(0, 1)) && !validationSets.two.includes(nif.substr(0, 2))) return false;
  const total = nif[0] * 9 + nif[1] * 8 + nif[2] * 7 + nif[3] * 6 + nif[4] * 5 + nif[5] * 4 + nif[6] * 3 + nif[7] * 2;
  const modulo11 = (Number(total) % 11);
  const checkDigit = modulo11 < 2 ? 0 : 11 - modulo11;
  return checkDigit === Number(nif[8]);
}

getAge

function getAge(birthDateString) {
  const today = new Date();
  const birthDate = new Date(birthDateString);
  const age = today.getFullYear() - birthDate.getFullYear();
  const m = today.getMonth() - birthDate.getMonth();
  if (m < 0 || (m === 0 && today.getDate() < birthDate.getDate())) {
    age--;
  }
  return age;
}

querySelector

document.querySelector("form");

FormData

const formData = new FormData(document.querySelector("form"));
if (!formData.has("escola")) {
  alert("Todos os campos são obrigatórios.");
  return false;
}
formData.get("escola");

Loops

for (let i = 0; i < 10; i++) {
  console.log(i);
}

for (let i = 0; i < 10; i++) {
  if (i === 5) {
    continue;
  }
  console.log(i);
}

for (let i = 0; i < 10; i++) {
  if (i === 5) {
    break;
  }
  console.log(i);
}

const arr = [1, 2, 3, 4, 5];
for (let i = 0; i < arr.length; i++) {
  console.log(arr[i]);
}

for (let i in arr) {
  console.log(arr[i]);
}

for (let i of arr) {
  console.log(i);
}

arr.forEach((i) => console.log(i));

arr.map((i) => console.log(i));

PHP

validateNIF

function validateNIF($nif) {
  $nif = trim($nif);
  $nif_split = str_split($nif);
  $nif_primeiros_digito = array(1, 2, 3, 5, 6, 7, 8, 9);
  if (is_numeric($nif) && strlen($nif) == 9 && in_array($nif_split[0], $nif_primeiros_digito)) {
    $check_digit = 0;
    for ($i = 0; $i < 8; $i++) {
      $check_digit += $nif_split[$i] * (10 - $i - 1);
    }
    $check_digit = 11 - ($check_digit % 11);
    $check_digit = $check_digit >= 10 ? 0 : $check_digit;
    if ($check_digit == $nif_split[8]) {
      return true;
    }
  }
  return false;
}

getAge

function getAge($birthDateString) {
  $today = new DateTime();
  $birthDate = new DateTime($birthDateString);
  $age = $today->diff($birthDate)->y;
  return $age;
}

Move Uploaded File

$target_folder = "uploads/";
$target_path = $target_folder . time() . '_' . $fotografia['name'];

move_uploaded_file($fotografia['tmp_name'], $site_dir . $target_path);

Redirect

header("Location: success.php?$query_string");
exit();

Check if POST

if ($_SERVER["REQUEST_METHOD"] != "POST") {
  header("Location: error.php?msg=InvalidRequestMethod");
  exit();
}

All File Validation

if (!isset($_FILES['fotografia'])) {
  header("Location: error.php?msg=MissingFields");
  exit();
}

$fotografia = $_FILES['fotografia'];

if ($fotografia['error'] != 0) {
  header("Location: error.php?msg=UploadError");
  exit();
}

$allowed_types = ['image/jpeg', 'image/png'];
$max_size = 5 * 1024 * 1024; // 5 MB

if (!in_array($fotografia['type'], $allowed_types) || $fotografia['size'] > $max_size) {
  header("Location: error.php?msg=InvalidImage");
  exit();
}

pr

function pr($var) {
  echo '<pre>';
  print_r($var);
  echo '</pre>';
}

Loops

for ($i = 0; $i < 10; $i++) {
  echo $i;
}

for ($i = 0; $i < 10; $i++) {
  if ($i === 5) {
      continue;
  }
  echo $i;
}

for ($i = 0; $i < 10; $i++) {
  if ($i === 5) {
      break;
  }
  echo $i;
}

$arr = array(1, 2, 3, 4, 5);
for ($i = 0; $i < count($arr); $i++) {
  echo $arr[$i];
}

foreach ($arr as $i) {
  echo $i;
}

foreach ($arr as $key => $value) {
  echo $key . ' ' . $value;
}

Coisas do Kraktoos

CSS

Tailwind.css

<script src="https://cdn.tailwindcss.com"></script>

Pico

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@picocss/pico@1" />

CSS Reset

html {
  box-sizing: border-box;
  font-size: 16px;
}

*, *:before, *:after {
  box-sizing: inherit;
}

body, h1, h2, h3, h4, h5, h6, p, ol, ul {
  margin: 0;
  padding: 0;
  font-weight: normal;
}

ol, ul {
  list-style: none;
}

img {
  max-width: 100%;
  height: auto;
}

PHP

Extract POST

extract($_POST, EXTR_PREFIX_ALL, 'form');

Extract GET

extract($_GET, EXTR_PREFIX_ALL, 'query');

Build Query String

$query_string = http_build_query($_POST + ['fotografia' => $target_path]);