gabriel 6 years ago
parent
commit
da0b337733
6 changed files with 522 additions and 2 deletions
  1. 23 0
      .drone.yml
  2. 9 0
      CheckSintaxBundle.php
  3. 432 0
      Command/CheckSintaxCommand.php
  4. 35 2
      README.md
  5. 9 0
      Resources/templates.txt
  6. 14 0
      composer.json

+ 23 - 0
.drone.yml

@@ -0,0 +1,23 @@
+pipeline:
+  build_branch:
+    image: docker.infra.flowdat.com/fd3/sf-php:latest
+    commands:
+      - chmod 0600 keys/*
+      - eval $(ssh-agent); ssh-add keys/gogs.drone.id_rsa
+      - git fetch --tags
+      - git remote add gogs ssh://git@gogs.infra.flowdat.com:222/VendorSoftwareFlowdat3/CheckSpellBundle.git
+      - git push gogs master:${DRONE_BRANCH} --tags
+    when:
+       event: [ push ]
+
+
+  build_tag:
+    image: docker.infra.flowdat.com/fd3/sf-php:latest
+    commands:
+      - chmod 0600 keys/*
+      - eval $(ssh-agent); ssh-add keys/gogs.drone.id_rsa
+      - git fetch
+      - git remote add gogs ssh://git@gogs.infra.flowdat.com:222/VendorSoftwareFlowdat3/CheckSpellBundle.git
+      - git push gogs --tags
+    when:
+       event: [ tag ]

+ 9 - 0
CheckSintaxBundle.php

@@ -0,0 +1,9 @@
+<?php
+
+namespace CheckSintaxBundle;
+
+use Symfony\Component\HttpKernel\Bundle\Bundle;
+
+class CheckSintaxBundle extends Bundle
+{
+}

+ 432 - 0
Command/CheckSintaxCommand.php

@@ -0,0 +1,432 @@
+<?php
+
+namespace CheckSintaxBundle\Command;
+
+use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Yaml\Yaml;
+
+class CheckSintaxCommand extends ContainerAwareCommand
+{
+    /**
+     * @var array|CheckChars
+     */
+    private $chars = [];
+    private $debug;
+
+    protected function configure()
+    {
+        $this
+            ->setName('check:sintax')
+            ->setDescription('Check sintax for those characters that need open and close')
+            ->addOption('dir', '', InputOption::VALUE_OPTIONAL, 'Directory to read all yaml files in it.', '')
+            ->addOption('yml', '', InputOption::VALUE_OPTIONAL, 'Path to read yaml file.', '')
+            ->addOption('string', '', InputOption::VALUE_OPTIONAL, 'String to check.', '')
+            ->addOption('debug', '', InputOption::VALUE_OPTIONAL, 'Debug mode.', false)
+            ->setHelp('Check sintax for those characters that need open and close');
+    }
+
+    /**
+     * @param InputInterface $input
+     * @param OutputInterface $output
+     * @return int Return 0 if OK, otherwise 1
+     */
+    protected function execute(InputInterface $input, OutputInterface $output)
+    {
+        $dir = $input->getOption("dir");
+        $fileYaml = $input->getOption("yml");
+        $string = $input->getOption("string");
+        $this->debug = $input->getOption("debug");
+        $this->loadParameters();
+        $error = "Nothing to do.";
+        if (trim($fileYaml) != "") {
+            $data = Yaml::parse(file_get_contents($fileYaml));
+            $error = $this->checkFileArray($data);
+        } elseif (strlen(trim($dir)) > 0) {
+            $error = $this->checkPathFile($dir);
+        } elseif (strlen(trim($string)) > 0) {
+            $error = $this->verifyString($string);
+        }
+        if (is_null($error)) {
+            $this->returnOK($output);
+            return 0;
+        } else {
+            $output->writeln($error);
+        }
+        return 0;
+    }
+
+    /**
+     * Load parameters form file.
+     */
+    private function loadParameters()
+    {
+        $fileLocator = $this->getContainer()->get('file_locator');
+        $templates = $fileLocator->locate('@CheckSintaxBundle/Resources/templates.txt');
+        $lines = explode(PHP_EOL, file_get_contents($templates));
+        foreach ($lines as $l) {
+            $ch = explode(":", trim($l));
+            if (count($ch) === 2) {
+                $this->chars[] = new CheckChars($ch[0], $ch[1]);
+            }
+        }
+    }
+
+    /**
+     * Write string ok.
+     * @param OutputInterface $output
+     */
+    private function returnOK(OutputInterface $output)
+    {
+        $output->writeln("OK!!!");
+    }
+
+    /**
+     * Write error found.
+     */
+    private function checkCharsArrayErrors()
+    {
+        $error = null;
+        foreach ($this->chars as $cc) {
+            if ($cc->getCounter() != 0) {
+                if ($cc->getCounter() > 0) {
+                    $error = "There is more character " . $cc->getOpen() . " open (" . $cc->getCounter() . ") than character " . $cc->getClose() . " close.";
+                } else {
+                    $error = "There is more character " . $cc->getClose() . " close (" . ($cc->getCounter() * -1) . ") than character " . $cc->getOpen() . " open.";
+                }
+            }
+        }
+        return $error;
+    }
+
+    /**
+     * Reset de counters chars.
+     */
+    private function resetCounters()
+    {
+        foreach ($this->chars as $cc) {
+            $cc->resetCounter();
+        }
+    }
+
+    /**
+     * @param string $dir Contains directory to read all files in it.
+     * @return string|null Return error.
+     */
+    private function checkPathFile($dir)
+    {
+        $files = scandir($dir);
+        $error = null;
+        foreach ($files as $file) {
+            if (is_file($dir . $file)) {
+                $errorTmp = $this->checkFileArray(Yaml::parse(file_get_contents($dir . $file)));
+                if (!is_null($errorTmp) && strlen(trim($errorTmp)) > 0) {
+                    if (is_null($error)) {
+                        $error = "\n$dir$file";
+                    } else {
+                        $error = "$error\n--------------------------------------------------------------------------------\n$dir$file";
+                    }
+                    $error = "$error\n$errorTmp\n";
+                }
+            }
+        }
+        return $error;
+    }
+
+    /**
+     * @param array $data Contains array with data to check.
+     * @param string $errorKey Contains key with error.
+     * @return string|null Return error or null if OK!
+     */
+    private function checkFileArray($data, $errorKey = "")
+    {
+        $error = null;
+        foreach ($data as $key => $value) {
+            if (is_array($value)) {
+                $error .= $this->checkFileArray($value, $errorKey . ($errorKey == "" ? "" : " -> ") . $key);
+            } else {
+                $this->checkString($value);
+                $errorTmp = $this->checkCharsArrayErrors();
+                if (!is_null($errorTmp)) {
+                    $errorTmp .= "\nError in $errorKey -> $key.";
+                    if ($this->debug) {
+                        $errorTmp .= "\n$value";
+                    }
+                    $errorTmp .= "\n################################################################################";
+                }
+                if (!is_null($errorTmp)) {
+                    if (is_null($error)) {
+                        $error = $errorTmp;
+                    } else {
+                        $error = "$error\n$errorTmp\n";
+                    }
+                    $this->resetCounters();
+                }
+            }
+        }
+        return $error;
+    }
+    //--------------
+    //--- STRING ---
+    //--------------
+    /**
+     * @param string $string Contains script bash.
+     */
+    private function checkString($string)
+    {
+        for ($i = 0, $size = (strlen($string) - 1); $i < $size;) {
+            $pos = $this->checkCharsArray($string[$i], $string[$i + 1]);
+            if ($pos == 0) {
+                $i++;
+            } else {
+                $i = $i + $pos;
+            }
+        }
+        if ($i <= $size) {
+            $this->checkCharsArray($string[$size], "");
+        }
+    }
+
+    /**
+     * @param string $ch Contians char to check.
+     * @param string $chplus Contains char +1.
+     * @return int Return position to advance.
+     */
+    private function checkCharsArray($ch, $chplus)
+    {
+        $pos = 0;
+        foreach ($this->chars as $cc) {
+            $pos = $cc->check($ch, $chplus);
+            if ($pos > 0) {
+                return $pos;
+            }
+        }
+        return $pos;
+    }
+
+    /**
+     * @param string $string Contians string to check
+     * @return null|string Return the $error value. If null it ok!!!
+     */
+    private function verifyString($string)
+    {
+        $error = null;
+        $string = trim($string);
+        if ($this->isJson($string)) {
+            $string = str_replace("\\r\\n", "", $string);
+            if ($this->isValidJson($string)) {
+                return null;
+            } else {
+                $error = $this->errorJson();
+            }
+        } else {
+            $this->checkString($string);
+            $error = $this->checkCharsArrayErrors();
+        }
+        return $error;
+    }
+
+    //------------
+    //--- JSON ---
+    //------------
+    /**
+     * @return string Return json error.
+     */
+    private function errorJson()
+    {
+        switch (json_last_error()) {
+            case JSON_ERROR_DEPTH:
+                $error = 'The maximum stack depth has been exceeded.';
+                break;
+            case JSON_ERROR_STATE_MISMATCH:
+                $error = 'Invalid or malformed JSON.';
+                break;
+            case JSON_ERROR_CTRL_CHAR:
+                $error = 'Control character error, possibly incorrectly encoded.';
+                break;
+            case JSON_ERROR_SYNTAX:
+                $error = 'Syntax error, malformed JSON.';
+                break;
+            // PHP >= 5.3.3
+            case JSON_ERROR_UTF8:
+                $error = 'Malformed UTF-8 characters, possibly incorrectly encoded.';
+                break;
+            // PHP >= 5.5.0
+            case JSON_ERROR_RECURSION:
+                $error = 'One or more recursive references in the value to be encoded.';
+                break;
+            // PHP >= 5.5.0
+            case JSON_ERROR_INF_OR_NAN:
+                $error = 'One or more NAN or INF values in the value to be encoded.';
+                break;
+            case JSON_ERROR_UNSUPPORTED_TYPE:
+                $error = 'A value of a type that cannot be encoded was given.';
+                break;
+            default:
+                $error = 'Unknown JSON error occured.';
+                break;
+        }
+        return "\n" . $error . "\n" . json_last_error_msg();
+    }
+
+    /**
+     * @param string $string Json as string.
+     * @return bool Return TRUE if is a valid json.
+     */
+    private function isJson($string)
+    {
+        if (substr($string, 0, 1) == "{" &&
+            substr($string, strlen($string) - 1, strlen($string)) == "}") {
+            for ($i = 1, $size = (strlen($string) - 1); $i < $size; $i++) {
+                if (strlen(trim($string[$i])) != 0) {
+                    // es el primer caracter despues de la llave de inicio, entonces tiene que ser una comilla doble
+                    return $string[$i] == '"';
+                }
+            }
+        } else {
+            return false;
+        }
+        return false;
+    }
+
+    /**
+     * @param string $string Json as string.
+     * @return bool Return TRUE if is a valid json.
+     */
+    private function isValidJson($string)
+    {
+        json_decode($string);
+        return (json_last_error() == JSON_ERROR_NONE);
+    }
+}
+
+class CheckChars
+{
+    /**
+     * @var string Contains open char.
+     */
+    private $open;
+    /**
+     * @var string Contains close char.
+     */
+    private $close;
+    /**
+     * @var string Contains the number of match. If open match then +1 if close match then -1.
+     */
+    private $counter;
+    /**
+     * @var boolean Tell if open and close are equals.
+     */
+    private $equals;
+
+    /**
+     * OneChar constructor.
+     * @param $open
+     * @param $close
+     */
+    public function __construct($open, $close)
+    {
+        $this->open = $open;
+        $this->close = $close;
+        $this->equals = $open == $close;
+        $this->counter = 0;
+    }
+
+    /**
+     * @param string $ch Contians char to check.
+     * @param string $chplus Contains char +1.
+     * @return int Return position to advance.
+     */
+    public function check($ch, $chplus)
+    {
+        // primero chequeo si estoy en una dupla, si es asi, entonces no realizo el chequeo de simple
+        $chplus = $ch . $chplus;
+        $pos = 0;
+        if ($chplus == $this->getOpen()) {
+            $this->foundOpen();
+            $pos = 2;
+        } elseif ($chplus == $this->getClose()) {
+            $this->foundClose();
+            $pos = 2;
+        } elseif ($ch == $this->getOpen()) {
+            $this->foundOpen();
+            $pos = 1;
+        } elseif ($ch == $this->getClose()) {
+            $this->foundClose();
+            $pos = 1;
+        }
+        return $pos;
+    }
+
+    /**
+     * @return mixed
+     */
+    public function getOpen()
+    {
+        return $this->open;
+    }
+
+    /**
+     * @param mixed $open
+     */
+    public function setOpen($open)
+    {
+        $this->open = $open;
+    }
+
+    /**
+     * @return mixed
+     */
+    public function getClose()
+    {
+        return $this->close;
+    }
+
+    /**
+     * @param mixed $close
+     */
+    public function setClose($close)
+    {
+        $this->close = $close;
+    }
+
+    /**
+     * Add 1 to counter
+     */
+    public function foundOpen()
+    {
+        $this->counter++;
+    }
+
+    /**
+     * Sub 1 to counter
+     */
+    public function foundClose()
+    {
+        $this->counter--;
+    }
+
+    /**
+     * Reset counter
+     */
+    public function resetCounter()
+    {
+        $this->counter = 0;
+    }
+
+    /**
+     * @return string
+     */
+    public function getCounter()
+    {
+        if ($this->equals) {
+            // si los valores de open y close con iguales y el counter es par, entonces es correcta la cantidad de llaves
+            return $this->counter % 2 == 0 ? 0 : $this->counter;
+        } else {
+            return $this->counter;
+        }
+    }
+}
+

+ 35 - 2
README.md

@@ -1,3 +1,36 @@
-# CheckSintaxBundle
+# DeviceBundle
 
-Cheque la sintaxis de los scripts que necesitan la verificación de los caracteres de apertura y cierre.
+- [Installation](#installation)
+- [Validator](#validators)
+
+## Installation
+
+**composer.json**:
+
+```javascript
+"repositories": [
+    {
+        "type": "vcs",
+        "url":  "ssh://git@infra.flowdat.com:222/VendorSoftwareFlowdat3/CheckSintaxBundle.git",
+        "options": {
+                "local_pk": "./keys/bitbucket.id_rsa"
+        }
+    }
+],
+"require": {
+    "ik/check-sintax-bundle": "dev-master"
+},
+```
+
+**app/AppKernel.php**:
+
+```php
+public function registerBundles()
+{
+    $bundles = [
+        new CheckSintaxBundle\CheckSintaxBundle(),
+    ];
+    .
+    .
+}
+```

+ 9 - 0
Resources/templates.txt

@@ -0,0 +1,9 @@
+\":\"
+\':\'
+{#:#}
+{%:%}
+{{:}}
+{:}
+[:]
+":"
+':'

+ 14 - 0
composer.json

@@ -0,0 +1,14 @@
+{
+    "name": "ik/check-sintax-bundle",
+    "description": "Flowdat 3 Device Bundle",
+    "keywords": ["Admin Generator", "admin", "validators", "bundle"],
+    "autoload": {
+        "psr-4": { "CheckSintaxBundle\\": "" }
+    },
+    "repositories": [
+        {
+            "type": "vcs",
+            "url": "ssh://git@infra.flowdat.com:222/VendorSoftwareFlowdat3/CheckSintaxBundle.git"
+        }
+    ]
+}