Browse Source

init symfony framework

master
ghost 9 months ago
parent
commit
d26999e405
  1. 20
      .env
  2. 10
      .gitignore
  3. 47
      README.md
  4. 17
      bin/console
  5. 68
      composer.json
  6. 2416
      composer.lock
  7. 21
      config-default.php
  8. 5
      config/bundles.php
  9. 19
      config/packages/cache.yaml
  10. 16
      config/packages/framework.yaml
  11. 10
      config/packages/routing.yaml
  12. 5
      config/preload.php
  13. 5
      config/routes.yaml
  14. 4
      config/routes/framework.yaml
  15. 24
      config/services.yaml
  16. 59
      crontab/sitemap.php
  17. 222
      library/icon.php
  18. 268
      library/sqlite.php
  19. 203
      public/css/app.css
  20. 36
      public/image.php
  21. 173
      public/index.php
  22. 114
      public/index.phtml
  23. 2
      public/robots.txt
  24. 21
      public/rss.phtml
  25. 0
      src/Controller/.gitignore
  26. 11
      src/Kernel.php
  27. 58
      symfony.lock

20
.env

@ -0,0 +1,20 @@
# In all environments, the following files are loaded if they exist,
# the latter taking precedence over the former:
#
# * .env contains default values for the environment variables needed by the app
# * .env.local uncommitted file with local overrides
# * .env.$APP_ENV committed environment-specific defaults
# * .env.$APP_ENV.local uncommitted environment-specific overrides
#
# Real environment variables win over .env files.
#
# DO NOT DEFINE PRODUCTION SECRETS IN THIS FILE NOR IN ANY OTHER COMMITTED FILES.
# https://symfony.com/doc/current/configuration/secrets.html
#
# Run "composer dump-env prod" to compile .env files for production use (requires symfony/flex >=1.2).
# https://symfony.com/doc/current/best_practices.html#use-environment-variables-for-infrastructure-configuration
###> symfony/framework-bundle ###
APP_ENV=dev
APP_SECRET=EDIT_ME
###< symfony/framework-bundle ###

10
.gitignore vendored

@ -0,0 +1,10 @@
###> symfony/framework-bundle ###
/.env.local
/.env.local.php
/.env.*.local
/config/secrets/prod/prod.decrypt.private.php
/public/bundles/
/var/
/vendor/
###< symfony/framework-bundle ###

47
README.md

@ -1,47 +0,0 @@
# kvazar-network webapp
Web-oriented content exploring platform for Kevacoin Blockchain
### requirements
```
php-8^
php-curl
php-mbstring
php-sqlite3
php-pdo
php-bcmath
php-gd
```
#### database
https://github.com/kvazar-network/database
##### MySQL
https://github.com/kvazar-network/webapp/tree/master
##### SQLite
https://github.com/kvazar-network/webapp/tree/sqlite
#### crontab
```
0 0 * * * /path-to/php /path-to/crontab/sitemap.php > /dev/null 2>&1
```
### nginx sef_mode example
```
location / {
try_files $uri $uri/ =404 @sef;
}
location @sef {
rewrite ^(/.*)$ /?$1 last;
}
```
### examples
#### yggdrasil
[http://[203:9fd0:95df:54d7:29db:5ee1:fe2d:95c7]](http://[203:9fd0:95df:54d7:29db:5ee1:fe2d:95c7])

17
bin/console

@ -0,0 +1,17 @@
#!/usr/bin/env php
<?php
use App\Kernel;
use Symfony\Bundle\FrameworkBundle\Console\Application;
if (!is_file(dirname(__DIR__).'/vendor/autoload_runtime.php')) {
throw new LogicException('Symfony Runtime is missing. Try running "composer require symfony/runtime".');
}
require_once dirname(__DIR__).'/vendor/autoload_runtime.php';
return function (array $context) {
$kernel = new Kernel($context['APP_ENV'], (bool) $context['APP_DEBUG']);
return new Application($kernel);
};

68
composer.json

@ -0,0 +1,68 @@
{
"type": "project",
"license": "MIT",
"minimum-stability": "stable",
"prefer-stable": true,
"require": {
"php": ">=8.2",
"ext-ctype": "*",
"ext-iconv": "*",
"symfony/console": "7.0.*",
"symfony/dotenv": "7.0.*",
"symfony/flex": "^2",
"symfony/framework-bundle": "7.0.*",
"symfony/runtime": "7.0.*",
"symfony/yaml": "7.0.*"
},
"require-dev": {
},
"config": {
"allow-plugins": {
"php-http/discovery": true,
"symfony/flex": true,
"symfony/runtime": true
},
"sort-packages": true
},
"autoload": {
"psr-4": {
"App\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"App\\Tests\\": "tests/"
}
},
"replace": {
"symfony/polyfill-ctype": "*",
"symfony/polyfill-iconv": "*",
"symfony/polyfill-php72": "*",
"symfony/polyfill-php73": "*",
"symfony/polyfill-php74": "*",
"symfony/polyfill-php80": "*",
"symfony/polyfill-php81": "*",
"symfony/polyfill-php82": "*"
},
"scripts": {
"auto-scripts": {
"cache:clear": "symfony-cmd",
"assets:install %PUBLIC_DIR%": "symfony-cmd"
},
"post-install-cmd": [
"@auto-scripts"
],
"post-update-cmd": [
"@auto-scripts"
]
},
"conflict": {
"symfony/symfony": "*"
},
"extra": {
"symfony": {
"allow-contrib": false,
"require": "7.0.*"
}
}
}

2416
composer.lock generated

File diff suppressed because it is too large Load Diff

21
config-default.php

@ -1,21 +0,0 @@
<?php
// Debug
ini_set('display_errors', '1');
ini_set('display_startup_errors', '1');
error_reporting(E_ALL);
// Application
define('BASE_URL', '');
define('PAGE_LIMIT', 10);
define('CACHE_ENABLED', false);
define('TRENDS_ENABLED', false); // alpha
define('TRENDS_SECONDS_OFFSET', 2592000);
define('TRENDS_MIN_LENGHT', 4);
define('TRENDS_LIMIT', 40);
// Database
define('DB_NAME', '../kvazar.sqlite');
define('DB_USERNAME', '');
define('DB_PASSWORD', '');

5
config/bundles.php

@ -0,0 +1,5 @@
<?php
return [
Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true],
];

19
config/packages/cache.yaml

@ -0,0 +1,19 @@
framework:
cache:
# Unique name of your app: used to compute stable namespaces for cache keys.
#prefix_seed: your_vendor_name/app_name
# The "app" cache stores to the filesystem by default.
# The data in this cache should persist between deploys.
# Other options include:
# Redis
#app: cache.adapter.redis
#default_redis_provider: redis://localhost
# APCu (not recommended with heavy random-write workloads as memory fragmentation can cause perf issues)
#app: cache.adapter.apcu
# Namespaced pools use the above "app" backend by default
#pools:
#my.dedicated.cache: null

16
config/packages/framework.yaml

@ -0,0 +1,16 @@
# see https://symfony.com/doc/current/reference/configuration/framework.html
framework:
secret: '%env(APP_SECRET)%'
#csrf_protection: true
# Note that the session will be started ONLY if you read or write from it.
session: true
#esi: true
#fragments: true
when@test:
framework:
test: true
session:
storage_factory_id: session.storage.factory.mock_file

10
config/packages/routing.yaml

@ -0,0 +1,10 @@
framework:
router:
# Configure how to generate URLs in non-HTTP contexts, such as CLI commands.
# See https://symfony.com/doc/current/routing.html#generating-urls-in-commands
#default_uri: http://localhost
when@prod:
framework:
router:
strict_requirements: null

5
config/preload.php

@ -0,0 +1,5 @@
<?php
if (file_exists(dirname(__DIR__).'/var/cache/prod/App_KernelProdContainer.preload.php')) {
require dirname(__DIR__).'/var/cache/prod/App_KernelProdContainer.preload.php';
}

5
config/routes.yaml

@ -0,0 +1,5 @@
controllers:
resource:
path: ../src/Controller/
namespace: App\Controller
type: attribute

4
config/routes/framework.yaml

@ -0,0 +1,4 @@
when@dev:
_errors:
resource: '@FrameworkBundle/Resources/config/routing/errors.xml'
prefix: /_error

24
config/services.yaml

@ -0,0 +1,24 @@
# This file is the entry point to configure your own services.
# Files in the packages/ subdirectory configure your dependencies.
# Put parameters here that don't need to change on each machine where the app is deployed
# https://symfony.com/doc/current/best_practices.html#use-parameters-for-application-configuration
parameters:
services:
# default configuration for services in *this* file
_defaults:
autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
# makes classes in src/ available to be used as services
# this creates a service per class whose id is the fully-qualified class name
App\:
resource: '../src/'
exclude:
- '../src/DependencyInjection/'
- '../src/Entity/'
- '../src/Kernel.php'
# add more service definitions when explicit configuration is needed
# please note that last definitions always *replace* previous ones

59
crontab/sitemap.php

@ -1,59 +0,0 @@
<?php
require_once(dirname(__FILE__) . '/../config.php');
require_once(dirname(__FILE__) . '/../library/sqlite.php');
$db = new SQLite(DB_NAME, DB_USERNAME, DB_PASSWORD);
// Generate url sets
$transaction = '<?xml version="1.0" encoding="UTF-8"?>';
$transaction .= '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1">';
$namespace = '<?xml version="1.0" encoding="UTF-8"?>';
$namespace .= '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1">';
$namespaces = [];
$transactions = [];
foreach ($db->getData(false, false, false, 0, 1000000) as $value) {
if (!in_array($value['namehash'], $namespaces)) {
$namespace .= '<loc>' . BASE_URL . $value['namehash'] . '</loc>';
}
if (!in_array($value['namehash'], $transactions)) {
$transaction .= '<loc>' . BASE_URL . $value['txid'] . '</loc>';
}
$namespaces[] = $value['namehash'];
$transactions[] = $value['txid'];
}
$namespace .= '</urlset>';
$transaction .= '</urlset>';
$handle = fopen(dirname(__FILE__) . '/../public/sitemap.transaction.xml', 'w');
fwrite($handle, $transaction);
fclose($handle);
$handle = fopen(dirname(__FILE__) . '/../public/sitemap.namespace.xml', 'w');
fwrite($handle, $namespace);
fclose($handle);
// Sitemap
$sitemap = '<?xml version="1.0" encoding="UTF-8"?>';
$sitemap .= '<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">';
$sitemap .= ' <sitemap>';
$sitemap .= ' <loc>' . BASE_URL . 'sitemap.namespace.xml</loc>';
$sitemap .= ' </sitemap>';
$sitemap .= ' <sitemap>';
$sitemap .= ' <loc>' . BASE_URL . 'sitemap.transaction.xml</loc>';
$sitemap .= ' </sitemap>';
$sitemap .= '</sitemapindex>';
$handle = fopen(dirname(__FILE__) . '/../public/sitemap.xml', 'w');
fwrite($handle, $sitemap);
fclose($handle);

222
library/icon.php

@ -1,222 +0,0 @@
<?php
final class Icon {
private $_width;
private $_height;
private $_hash;
private $_spriteZ = 800;
public function generateImageResource($hash, $width, $height, $filter = false, $radius = 0) {
$this->_width = $width;
$this->_height = $height;
$this->_hash = $hash;
$csh = hexdec(substr($this->_hash, 0, 1)); // corner sprite shape
$ssh = hexdec(substr($this->_hash, 1, 1)); // side sprite shape
$xsh = hexdec(substr($this->_hash, 2, 1)) & 7; // center sprite shape
$cro = hexdec(substr($this->_hash, 3, 1)) & 3; // corner sprite rotation
$sro = hexdec(substr($this->_hash, 4, 1)) & 3; // side sprite rotation
$xbg = hexdec(substr($this->_hash, 5, 1)) % 2; // center sprite background
$cfr = hexdec(substr($this->_hash, 6, 2));
$cfg = hexdec(substr($this->_hash, 8, 2));
$cfb = hexdec(substr($this->_hash, 10, 2));
$sfr = hexdec(substr($this->_hash, 12, 2));
$sfg = hexdec(substr($this->_hash, 14, 2));
$sfb = hexdec(substr($this->_hash, 16, 2));
$identicon = imagecreatetruecolor($this->_spriteZ * 3, $this->_spriteZ * 3);
if (function_exists('imageantialias')) {
imageantialias($identicon, TRUE);
}
$bg = imagecolorallocate($identicon, 255, 255, 255);
imagefilledrectangle($identicon, 0, 0, $this->_spriteZ, $this->_spriteZ, $bg);
$corner = $this->_getSprite($csh, $cfr, $cfg, $cfb, $cro);
imagecopy($identicon, $corner, 0, 0, 0, 0, $this->_spriteZ, $this->_spriteZ);
$corner = imagerotate($corner, 90, $bg);
imagecopy($identicon, $corner, 0, $this->_spriteZ * 2, 0, 0, $this->_spriteZ, $this->_spriteZ);
$corner = imagerotate($corner, 90, $bg);
imagecopy($identicon, $corner, $this->_spriteZ * 2, $this->_spriteZ * 2, 0, 0, $this->_spriteZ, $this->_spriteZ);
$corner = imagerotate($corner, 90, $bg);
imagecopy($identicon, $corner, $this->_spriteZ * 2, 0, 0, 0, $this->_spriteZ, $this->_spriteZ);
$side = $this->_getSprite($ssh, $sfr, $sfg, $sfb, $sro);
imagecopy($identicon, $side, $this->_spriteZ, 0, 0, 0, $this->_spriteZ, $this->_spriteZ);
$side = imagerotate($side, 90, $bg);
imagecopy($identicon, $side, 0, $this->_spriteZ, 0, 0, $this->_spriteZ, $this->_spriteZ);
$side = imagerotate($side, 90, $bg);
imagecopy($identicon, $side, $this->_spriteZ, $this->_spriteZ * 2, 0, 0, $this->_spriteZ, $this->_spriteZ);
$side = imagerotate($side, 90, $bg);
imagecopy($identicon, $side, $this->_spriteZ * 2, $this->_spriteZ, 0, 0, $this->_spriteZ, $this->_spriteZ);
$center = $this->_getCenter($xsh, $cfr, $cfg, $cfb, $sfr, $sfg, $sfb, $xbg);
imagecopy($identicon, $center, $this->_spriteZ, $this->_spriteZ, 0, 0, $this->_spriteZ, $this->_spriteZ);
imagecolortransparent($identicon, $bg);
$resized = imagecreatetruecolor($this->_width, $this->_height);
if (function_exists('imageantialias')) {
imageantialias($resized, TRUE);
}
$bg = imagecolorallocate($resized, 255, 255, 255);
imagefilledrectangle($resized, 0, 0, $this->_width, $this->_height, $bg);
imagecopyresampled($resized, $identicon, 0, 0, (imagesx($identicon) - $this->_spriteZ * 3) / 2, (imagesx($identicon) - $this->_spriteZ * 3) / 2, $this->_width, $this->_height, $this->_spriteZ * 3, $this->_spriteZ * 3);
if ($filter) {
imagefilter($resized, $filter);
}
if ($radius) {
imagearc($resized, $radius-1, $radius-1, $radius*2, $radius*2, 180, 270, $bg);
imagefilltoborder($resized, 0, 0, $bg, $bg);
imagearc($resized, $this->_width-$radius, $radius-1, $radius*2, $radius*2, 270, 0, $bg);
imagefilltoborder($resized, $this->_width-1, 0, $bg, $bg);
imagearc($resized, $radius-1, $this->_height-$radius, $radius*2, $radius*2, 90, 180, $bg);
imagefilltoborder($resized, 0, $this->_height-1, $bg, $bg);
imagearc($resized, $this->_width-$radius, $this->_height-$radius, $radius*2, $radius*2, 0, 90, $bg);
imagefilltoborder($resized, $this->_width-1, $this->_height-1, $bg, $bg);
imagecolortransparent($resized, $bg);
}
ob_start();
imagepng($resized);
imagedestroy($resized);
return ob_get_clean();
}
private function _getSprite($shape, $R, $G, $B, $rotation) {
$sprite = imagecreatetruecolor($this->_spriteZ, $this->_spriteZ);
if (function_exists('imageantialias')) {
imageantialias($sprite, TRUE);
}
$fg = imagecolorallocate($sprite, $R, $G, $B);
$bg = imagecolorallocate($sprite, 255, 255, 255);
imagefilledrectangle($sprite, 0, 0, $this->_spriteZ, $this->_spriteZ, $bg);
switch ($shape) {
case 0: // triangle
$shape = array(0.5, 1, 1, 0, 1, 1);
break;
case 1: // parallelogram
$shape = array(0.5, 0, 1, 0, 0.5, 1, 0, 1);
break;
case 2: // mouse ears
$shape = array(0.5, 0, 1, 0, 1, 1, 0.5, 1, 1, 0.5);
break;
case 3: // ribbon
$shape = array(0, 0.5, 0.5, 0, 1, 0.5, 0.5, 1, 0.5, 0.5);
break;
case 4: // sails
$shape = array(0, 0.5, 1, 0, 1, 1, 0, 1, 1, 0.5);
break;
case 5: // fins
$shape = array(1, 0, 1, 1, 0.5, 1, 1, 0.5, 0.5, 0.5);
break;
case 6: // beak
$shape = array(0, 0, 1, 0, 1, 0.5, 0, 0, 0.5, 1, 0, 1);
break;
case 7: // chevron
$shape = array(0, 0, 0.5, 0, 1, 0.5, 0.5, 1, 0, 1, 0.5, 0.5);
break;
case 8: // fish
$shape = array(0.5, 0, 0.5, 0.5, 1, 0.5, 1, 1, 0.5, 1, 0.5, 0.5, 0, 0.5);
break;
case 9: // kite
$shape = array(0, 0, 1, 0, 0.5, 0.5, 1, 0.5, 0.5, 1, 0.5, 0.5, 0, 1);
break;
case 10: // trough
$shape = array(0, 0.5, 0.5, 1, 1, 0.5, 0.5, 0, 1, 0, 1, 1, 0, 1);
break;
case 11: // rays
$shape = array(0.5, 0, 1, 0, 1, 1, 0.5, 1, 1, 0.75, 0.5, 0.5, 1, 0.25);
break;
case 12: // double rhombus
$shape = array(0, 0.5, 0.5, 0, 0.5, 0.5, 1, 0, 1, 0.5, 0.5, 1, 0.5, 0.5, 0, 1);
break;
case 13: // crown
$shape = array(0, 0, 1, 0, 1, 1, 0, 1, 1, 0.5, 0.5, 0.25, 0.5, 0.75, 0, 0.5, 0.5, 0.25);
break;
case 14: // radioactive
$shape = array(0, 0.5, 0.5, 0.5, 0.5, 0, 1, 0, 0.5, 0.5, 1, 0.5, 0.5, 1, 0.5, 0.5, 0, 1);
break;
default: // tiles
$shape = array(0, 0, 1, 0, 0.5, 0.5, 0.5, 0, 0, 0.5, 1, 0.5, 0.5, 1, 0.5, 0.5, 0, 1);
break;
}
for ($i = 0; $i < count($shape); $i++)
$shape[$i] = $shape[$i] * $this->_spriteZ;
imagefilledpolygon($sprite, $shape, $fg);
for ($i = 0; $i < $rotation; $i++)
$sprite = imagerotate($sprite, 90, $bg);
return $sprite;
}
private function _getCenter($shape, $fR, $fG, $fB, $bR, $bG, $bB, $usebg) {
$sprite = imagecreatetruecolor($this->_spriteZ, $this->_spriteZ);
if (function_exists('imageantialias')) {
imageantialias($sprite, TRUE);
}
$fg = imagecolorallocate($sprite, $fR, $fG, $fB);
if ($usebg > 0 && (abs($fR - $bR) > 127 || abs($fG - $bG) > 127 || abs($fB - $bB) > 127))
$bg = imagecolorallocate($sprite, $bR, $bG, $bB); else
$bg = imagecolorallocate($sprite, 255, 255, 255);
imagefilledrectangle($sprite, 0, 0, $this->_spriteZ, $this->_spriteZ, $bg);
switch ($shape) {
case 0: // empty
$shape = array();
break;
case 1: // fill
$shape = array(0, 0, 1, 0, 1, 1, 0, 1);
break;
case 2: // diamond
$shape = array(0.5, 0, 1, 0.5, 0.5, 1, 0, 0.5);
break;
case 3: // reverse diamond
$shape = array(0, 0, 1, 0, 1, 1, 0, 1, 0, 0.5, 0.5, 1, 1, 0.5, 0.5, 0, 0, 0.5);
break;
case 4: // cross
$shape = array(0.25, 0, 0.75, 0, 0.5, 0.5, 1, 0.25, 1, 0.75, 0.5, 0.5, 0.75, 1, 0.25, 1, 0.5, 0.5, 0, 0.75, 0, 0.25, 0.5, 0.5);
break;
case 5: // morning star
$shape = array(0, 0, 0.5, 0.25, 1, 0, 0.75, 0.5, 1, 1, 0.5, 0.75, 0, 1, 0.25, 0.5);
break;
case 6: // small square
$shape = array(0.33, 0.33, 0.67, 0.33, 0.67, 0.67, 0.33, 0.67);
break;
case 7: // checkerboard
$shape = array(0, 0, 0.33, 0, 0.33, 0.33, 0.66, 0.33, 0.67, 0, 1, 0, 1, 0.33, 0.67, 0.33, 0.67, 0.67, 1, 0.67, 1, 1, 0.67, 1, 0.67, 0.67, 0.33, 0.67, 0.33, 1, 0, 1, 0, 0.67, 0.33, 0.67, 0.33, 0.33, 0, 0.33);
break;
}
for ($i = 0; $i < count($shape); $i++)
$shape[$i] = $shape[$i] * $this->_spriteZ;
if (count($shape) > 0)
imagefilledpolygon($sprite, $shape, $fg);
return $sprite;
}
}

268
library/sqlite.php

@ -1,268 +0,0 @@
<?php
class SQLite {
private PDO $_db;
public function __construct(string $database, string $username, string $password) {
try {
$this->_db = new PDO('sqlite:' . $database, $username, $password);
$this->_db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->_db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
$this->_db->setAttribute(PDO::ATTR_TIMEOUT, 600);
$this->_db->query('
CREATE TABLE IF NOT EXISTS "namespace"(
"nameSpaceId" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL CHECK("nameSpaceId">=0),
"timeIndexed" INTEGER NOT NULL CHECK("timeIndexed">=0),
"hash" CHAR(34) NOT NULL,
CONSTRAINT "hash_UNIQUE"
UNIQUE("hash")
)
');
$this->_db->query('
CREATE TABLE IF NOT EXISTS "block"(
"blockId" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL CHECK("blockId">=0),
"timeIndexed" INTEGER NOT NULL CHECK("timeIndexed">=0),
"lostTransactions" INTEGER NOT NULL CHECK("lostTransactions">=0)
)
');
$this->_db->query('
CREATE TABLE IF NOT EXISTS "data"(
"dataId" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL CHECK("dataId">=0),
"nameSpaceId" INTEGER NOT NULL CHECK("nameSpaceId">=0),
"blockId" INTEGER NOT NULL CHECK("blockId">=0),
"time" INTEGER NOT NULL CHECK("time">=0),
"timeIndexed" INTEGER NOT NULL CHECK("timeIndexed">=0),
"size" INTEGER NOT NULL,
"ns" TEXT NOT NULL CHECK("ns" IN(\'0\', \'1\')),
"deleted" TEXT NOT NULL CHECK("deleted" IN(\'0\', \'1\')),
"txid" CHAR(64) NOT NULL,
"key" TEXT NOT NULL,
"value" TEXT NOT NULL,
CONSTRAINT "txid_UNIQUE"
UNIQUE("txid"),
CONSTRAINT "fk_data_namespace"
FOREIGN KEY("nameSpaceId")
REFERENCES "namespace"("nameSpaceId"),
CONSTRAINT "fk_data_block"
FOREIGN KEY("blockId")
REFERENCES "block"("blockId")
)
');
$this->_db->query('CREATE INDEX IF NOT EXISTS "data.fk_data_namespase_idx" ON "data" ("nameSpaceId")');
$this->_db->query('CREATE INDEX IF NOT EXISTS "data.fk_data_block_idx" ON "data" ("blockId")');
$this->_db->query('CREATE INDEX IF NOT EXISTS "data.deleted_INDEX" ON "data" ("deleted")');
$this->_db->query('CREATE INDEX IF NOT EXISTS "data.ns_INDEX" ON "data" ("ns")');
} catch(PDOException $e) {
trigger_error($e->getMessage());
}
}
public function getNamespaceValueByNS(string $ns) {
try {
$query = $this->_db->prepare('SELECT `data`.`value` AS `value`
FROM `data`
JOIN `namespace` ON (`namespace`.`nameSpaceId` = `data`.`nameSpaceId`)
WHERE `namespace`.`hash` = ?
AND `data`.`ns` = "1"
-- AND `data`.`deleted` = "0" --
ORDER BY `data`.`blockId` DESC
LIMIT 1');
$query->execute([$ns]);
$result = $query->fetch();
return $result ? $result['value'] : '';
} catch(PDOException $e) {
trigger_error($e->getMessage());
return false;
}
}
public function getNamespaceHashByTX(string $txid) {
try {
$query = $this->_db->prepare('SELECT `namespace`.`hash`
FROM `namespace`
JOIN `data` ON (`data`.`nameSpaceId` = `namespace`.`nameSpaceId`)
WHERE `data`.`txid` = ?');
$query->execute([$txid]);
return $query->rowCount() ? $query->fetch()['hash'] : '';
} catch(PDOException $e) {
trigger_error($e->getMessage());
return false;
}
}
public function getData(string $namehash = '', string $txid = '', string $search = '', int $start = 0, int $limit = 10) {
try {
if ($txid) {
$query = $this->_db->prepare('SELECT `block`.`blockId` AS `block`,
`namespace`.`hash` AS `namehash`,
`data`.`time` AS `time`,
`data`.`key` AS `key`,
`data`.`value` AS `value`,
`data`.`txid` AS `txid`
FROM `data`
JOIN `block` ON (`block`.`blockId` = `data`.`blockId`)
JOIN `namespace` ON (`namespace`.`nameSpaceId` = `data`.`nameSpaceId`)
WHERE `data`.`txid` = ?
AND `data`.`ns` = "0"
-- AND `data`.`deleted` = "0" --
ORDER BY `block`.`blockId` DESC
LIMIT ' . (int) $start . ',' . (int) $limit);
$query->execute([$txid]);
} else if ($namehash) {
$query = $this->_db->prepare('SELECT `block`.`blockId` AS `block`,
`namespace`.`hash` AS `namehash`,
`data`.`time` AS `time`,
`data`.`key` AS `key`,
`data`.`value` AS `value`,
`data`.`txid` AS `txid`
FROM `data`
JOIN `block` ON (`block`.`blockId` = `data`.`blockId`)
JOIN `namespace` ON (`namespace`.`nameSpaceId` = `data`.`nameSpaceId`)
WHERE `namespace`.`hash` = ?
AND `data`.`ns` = "0"
-- AND `data`.`deleted` = "0" --
ORDER BY `block`.`blockId` DESC
LIMIT ' . (int) $start . ',' . (int) $limit);
$query->execute([$namehash]);
} else if ($search) {
$query = $this->_db->prepare('SELECT `block`.`blockId` AS `block`,
`namespace`.`hash` AS `namehash`,
`data`.`time` AS `time`,
`data`.`key` AS `key`,
`data`.`value` AS `value`,
`data`.`txid` AS `txid`
FROM `data`
JOIN `block` ON (`block`.`blockId` = `data`.`blockId`)
JOIN `namespace` ON (`namespace`.`nameSpaceId` = `data`.`nameSpaceId`)
WHERE (`data`.`key` LIKE :search
OR `data`.`value` LIKE :search
OR `block`.`blockId` LIKE :search
OR `namespace`.`hash` LIKE :search
OR `data`.`txid` LIKE :search)
AND `data`.`ns` = "0"
-- AND `data`.`deleted` = "0" --
ORDER BY `block`.`blockId` DESC
LIMIT ' . (int) $start . ',' . (int) $limit);
$query->bindValue(':search', '%' . $search . '%', PDO::PARAM_STR);
$query->execute();
} else {
$query = $this->_db->prepare('SELECT `block`.`blockId` AS `block`,
`namespace`.`hash` AS `namehash`,
`data`.`time` AS `time`,
`data`.`key` AS `key`,
`data`.`value` AS `value`,
`data`.`txid` AS `txid`
FROM `data`
JOIN `block` ON (`block`.`blockId` = `data`.`blockId`)
JOIN `namespace` ON (`namespace`.`nameSpaceId` = `data`.`nameSpaceId`)
WHERE `data`.`ns` = "0"
-- AND `data`.`deleted` = "0" --
ORDER BY `block`.`blockId` DESC
LIMIT ' . (int) $start . ',' . (int) $limit);
$query->execute();
}
$result = $query->fetchAll();
return $result ? $result : [];
} catch(PDOException $e) {
trigger_error($e->getMessage());
return false;
}
}
public function getTrends(int $offset = 0) {
try {
$query = $this->_db->prepare('SELECT `block`.`blockId` AS `block`,
`namespace`.`hash` AS `namehash`,
`data`.`time` AS `time`,
`data`.`key` AS `key`,
`data`.`value` AS `value`,
`data`.`txid` AS `txid`
FROM `data`
JOIN `block` ON (`block`.`blockId` = `data`.`blockId`)
JOIN `namespace` ON (`namespace`.`nameSpaceId` = `data`.`nameSpaceId`)
WHERE `data`.`ns` = "0"
AND `data`.`time` >= ' . (int) $offset . '
-- AND `data`.`deleted` = "0" --
ORDER BY `block`.`blockId` DESC');
$query->execute();
$result = $query->fetchAll();
return $result ? $result : [];
} catch(PDOException $e) {
trigger_error($e->getMessage());
return false;
}
}
}

203
public/css/app.css

@ -1,203 +0,0 @@
button::-moz-focus-inner {
border: 0;
padding: 0;
margin-top:-2px;
margin-bottom: -2px;
}
* {
padding: 0;
margin: 0;
}
input, button {
opacity: 0.8;
color: #000;
background: #ABA6B7;
border: 0;
border-radius: 3px;
height: 18px;
line-height: 18px;
outline: none;
text-align: center;
}
body {
color: #BFBACC;
background-color: #000;
font-family: Sans-Serif, Arial;
font-size: 14px;
font-weight: normal;
line-height: 1.8;
}
a {
color: #ABA6B7;
text-decoration: none;
-moz-transition: all .5s ease-in;
-o-transition: all .5s ease-in;
/* issue #2
-webkit-transition: all .5s ease-in;
transition: all .5s ease-in; */
}
a:hover {
color: #BFBACC;
-webkit-transition: all .5s ease-in; /* issue #2 */
}
img {
opacity: 0.8;
-moz-transition: all .5s ease-in;
-o-transition: all .5s ease-in;
-webkit-transition: all .5s ease-in;
transition: all .5s ease-in;
}
img.shine,
img:hover {
opacity: 1
}
.logo {
font-size: 20px;
letter-spacing: .2em;
margin-right:-.2em;
}
.d-block {
display: block;
}
.of-a {
overflow: auto
}
.f-s-12 {
font-size: 12px;
}
.f-s-16 {
font-size: 16px;
}
.f-s-20 {
font-size: 18px;
}
.t-center {
text-align: center;
}
.b-g::before {
content: "";
background-image: linear-gradient(to left, #9B94BF, #000);
height: 1px;
width: 50%;
max-width: 360px;
display: inline-block;
}
.b-g::after {
content: "";
background-image: linear-gradient(to right, #9B94BF, #000);
height: 1px;
width: 50%;
max-width: 360px;
display: inline-block;
}
.br-50 {
border-radius: 50%;
}
.c-0,
.c-0:active,
.c-0:visited,
.c-0:hover {
color: #FFF;
}
.c-1,
.c-1:active,
.c-1:visited,
.c-1:hover {
color: #BFBACC;
}
.c-2,
.c-2:active,
.c-2:visited,
.c-2:hover {
color: #9ba5af;
}
.cursor-pointer {
cursor: pointer;
}
.p-8 {
padding: 8px;
}
@-moz-document url-prefix() {
.p-8 {
padding: 4px;
}
}
.px-16 {
padding-left: 16px;
padding-right: 16px;
}
.py-27 {
padding-top: 27px;
padding-bottom: 27px;
}
.py-54 {
padding-top: 54px;
padding-bottom: 54px;
}
.pt-27 {
padding-top: 27px;
}
.pt-54 {
padding-top: 54px;
}
.pb-16 {
padding-bottom: 16px;
}
.pb-27 {
padding-bottom: 27px;
}
.pb-36 {
padding-bottom: 36px;
}
.mx-a {
margin-left: auto;
margin-right: auto;
}
.mb-16 {
margin-bottom: 16px
}
.mb-20 {
margin-bottom: 20px
}
.mb-36 {
margin-bottom: 36px
}
.mw-560 {
max-width: 560px;
}

36
public/image.php

@ -1,36 +0,0 @@
<?php
require_once('../config.php');
require_once('../library/icon.php');
if (isset($_GET['hash'])) {
$hash = md5($_GET['hash']);
$width = isset($_GET['width']) ? (int) $_GET['width'] : 60;
$height = isset($_GET['height']) ? (int) $_GET['height'] : 60;
$radius = isset($_GET['radius']) ? (int) $_GET['radius'] : 0;
header("Content-Type: image/png");
if (CACHE_ENABLED) {
$filename = dirname(__FILE__) . '/../cache/' . $hash . '.png';
if (!file_exists($filename)) {
$icon = new Icon();
file_put_contents($filename, $icon->generateImageResource($hash, $width, $height, false, $radius));
}
echo file_get_contents($filename);
} else {
$icon = new Icon();
echo $icon->generateImageResource($hash, $width, $height, false, $radius);
}
}

173
public/index.php

@ -1,172 +1,9 @@
<?php <?php
require_once(__DIR__ . '/../config.php'); use App\Kernel;
require_once(__DIR__ . '/../library/icon.php');
require_once(__DIR__ . '/../library/sqlite.php');
$query = isset($_GET['q']) ? preg_replace('/[^\w\s]+/u', '', urldecode($_GET['q'])) : ''; require_once dirname(__DIR__).'/vendor/autoload_runtime.php';
$ns = '';
$tx = '';
$page = 0;
$rss = false;
if (isset($_SERVER['REQUEST_URI'])) { return function (array $context) {
return new Kernel($context['APP_ENV'], (bool) $context['APP_DEBUG']);
$q = explode('/', $_SERVER['REQUEST_URI']); };
if (isset($q[1])) {
if ($q[1] == 'rss') {
$rss = true;
} else if (strlen($q[1]) == 34) {
$ns = preg_replace('/[^a-zA-Z0-9]+/', '', $q[1]);
} else if (strlen($q[1]) == 64) {
$tx = preg_replace('/[^a-zA-Z0-9]+/', '', $q[1]);
} else if (preg_match('/[0-9]+/', $q[1])) {
$page = (int) $q[1];
}
}
if (isset($q[2])) {
if ($q[2] == 'rss') {
$rss = true;
} else if (strlen($q[2]) == 34) {
$ns = preg_replace('/[^a-zA-Z0-9]+/', '', $q[2]);
} else if (preg_match('/[0-9]+/', $q[2])) {
$page = (int) $q[2];
}
}
}
if ($query) {
$rss = isset($_GET['rss']) ? true : false;
}
if ($page > 0) {
$limit = PAGE_LIMIT * $page - PAGE_LIMIT;
} else {
$limit = PAGE_LIMIT * $page;
}
$db = new SQLite(DB_NAME, DB_USERNAME, DB_PASSWORD);
if ($ns) {
$namespaceHash = $ns;
$namespaceValue = $db->getNamespaceValueByNS($ns);
} else if ($tx) {
$namespaceHash = $db->getNamespaceHashByTX($tx);
$namespaceValue = $db->getNamespaceValueByNS($namespaceHash);
} else {
$namespaceHash = false;
$namespaceValue = false;
}
$trends = [];
if (TRENDS_ENABLED) {
foreach ($db->getTrends(time() - TRENDS_SECONDS_OFFSET) as $value) {
foreach ((array) explode(' ', strip_tags(html_entity_decode(nl2br(trim($value['key']))))) as $trend) {
if (strlen($trend) >= TRENDS_MIN_LENGHT) {
$trend = strtolower($trend);
if (isset($trends[$trend])) {
$trends[$trend]++;
} else {
$trends[$trend] = 1;
}
}
}
foreach ((array) explode(' ', strip_tags(html_entity_decode(nl2br(trim($value['value']))))) as $trend) {
if (strlen($trend) >= TRENDS_MIN_LENGHT) {
$trend = strtolower($trend);
if (isset($trends[$trend])) {
$trends[$trend]++;
} else {
$trends[$trend] = 1;
}
}
}
}
arsort($trends);
$trends = array_slice($trends, 0, TRENDS_LIMIT);
$trends = array_flip($trends);
}
$data = [];
foreach ($db->getData($ns, $tx, $query, $limit, PAGE_LIMIT) as $value) {
$data[] = [
'namehash' => $value['namehash'],
'block' => $value['block'],
'txid' => $value['txid'],
'time' => date(($rss ? 'r' : 'd-m-Y H:i'), $value['time']),
'key' => $rss ? htmlentities(strip_tags(trim($value['key'])), ENT_XML1) : nl2br(trim($value['key'])),
'value' => $rss ? htmlentities(strip_tags(trim($value['value'])), ENT_XML1): nl2br(trim($value['value'])),
];
}
$older = false;
$newer = false;
if (!in_array($page, [0, 1])) {
if ($page == 2) {
$newer = ($ns ? $ns : '');
} else {
$newer = ($ns ? $ns . '/' . ($page - 1) : ($page - 1));
}
if ($query) {
$newer = $newer . '?q=' . $query;
}
}
if ($data) {
if (in_array($page, [0, 1])) {
$older = ($ns ? $ns . '/2' : '2');
} else {
$older = ($ns ? $ns . '/' . ($page + 1) : ($page + 1));
}
if ($query) {
$older = $older . '?q=' . $query;
}
}
if ($ns) {
if ($page) {
$hrefThisPage = $ns . '/' . $page;
} else {
$hrefThisPage = $ns;
}
} else {
if ($page) {
$hrefThisPage = $page;
} else {
$hrefThisPage = '';
}
}
if ($rss) {
header('Content-type: application/xml');
require_once('rss.phtml');
} else {
require_once('index.phtml');
}

114
public/index.phtml

@ -1,114 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="<?php echo BASE_URL; ?>css/app.css?v=9" />
<meta charset="UTF-8" />
<meta name="description" content="Open Source Content Exploring Platform for Kevacoin Blockchain" />
<?php if (!$tx) { ?>
<meta name="robots" content="noindex,follow" />
<?php } ?>
<link rel="icon" type="image/png" href="<?php echo BASE_URL; ?>image.php?hash=<?php echo $namespaceHash; ?>&radius=30" />
<?php if ($ns) { ?>
<?php if ($page) { ?>
<title><?php echo $namespaceValue ? $namespaceValue : $ns; ?> | PART <?php echo $page; ?> | KVAZAR</title>
<?php } else { ?>
<title><?php echo $namespaceValue ? $namespaceValue : $ns; ?> | KVAZAR</title>
<?php } ?>
<?php } else { ?>
<?php if ($page) { ?>
<title>KVAZAR | PART <?php echo $page; ?></title>
<?php } else if ($tx) { ?>
<title><?php echo $tx && isset($data[0]['key']) ? $data[0]['key'] : $tx; ?> | <?php echo ($namespaceValue ? $namespaceValue : ($namespaceHash ? $namespaceHash : false)); ?> | KVAZAR</title>
<?php } else if ($query) { ?>
<title>KVAZAR | SEARCH | <?php echo $query; ?></title>
<?php } else { ?>
<title>KVAZAR</title>
<?php } ?>
<?php } ?>
</head>
<body>
<div class="t-center px-16 pt-54">
<div class="mx-a mw-560 px-16">
<div class="mb-20">
<a class="logo f-s-20 c-0" href="<?php echo BASE_URL; ?>">KVAZAR</a>
</div>
<?php if ($ns) { ?>
<div class="mx-a mw-560 px-16 pb-16">
<img class="br-50 shine" src="<?php echo BASE_URL; ?>image.php?hash=<?php echo $ns; ?>" alt="<?php echo $ns; ?>" />
</div>
<?php } ?>
<div class="mb-36 c-1"><?php echo $namespaceValue ? $namespaceValue : 'Observe Kevacoin Universe'; ?></div>
</div>
</div>
<div class="t-center px-16 pb-36">
<div class="b-g"></div>
</div>
<?php if ($trends && !$ns && !$tx && !$page && !$q) { ?>
<div class="t-center px-16">
<div class="mx-a mw-560 px-16">
<?php foreach ($trends as $trend) { ?>
#<a href="<?php echo BASE_URL; ?>?q=<?php echo $trend; ?>"><?php echo $trend; ?></a>
<?php } ?>
</div>
</div>
<div class="t-center px-16 py-27">
<div class="b-g"></div>
</div>
<?php } ?>
<?php foreach ($data as $item) { ?>
<div class="t-center px-16">
<div class="mx-a mw-560 px-16">
<?php if (!$ns) { ?>
<div class="mx-a mw-560 mb-16">
<a href="<?php echo BASE_URL; ?><?php echo $item['namehash']; ?>">
<img class="br-50" src="<?php echo BASE_URL; ?>image.php?hash=<?php echo $item['namehash']; ?>" alt="<?php echo $item['namehash']; ?>" />
</a>
</div>
<?php } ?>
<?php if (!$tx) { ?>
<a class="d-block" href="<?php echo BASE_URL; ?><?php echo $item['txid']; ?>">
<?php } ?>
<div class="f-s-16 mb-16 of-a">
<?php echo $item['key']; ?>
</div>
<div class="mb-20 of-a"><?php echo $item['value']; ?></div>
<div class="f-s-12">
<?php echo $item['time']; ?> in <?php echo $item['block']; ?>
</div>
<?php if (!$tx) { ?>
</a>
<?php } ?>
</div>
</div>
<div class="t-center px-16 py-27">
<div class="b-g"></div>
</div>
<?php } ?>
<?php if (!$tx && ($newer !== false || $older !== false)) { ?>
<div class="t-center pt-16 pb-27">
<?php if ($newer !== false) { ?>
<a href="<?php echo BASE_URL; ?><?php echo $newer; ?>"<?php echo $newer ? ' rel="nofollow"' : false; ?>>newer</a>
<?php } ?>
<?php if ($newer !== false && $older !== false) { ?>
|
<?php } ?>
<?php if ($older !== false) { ?>
<a href="<?php echo BASE_URL; ?><?php echo $older; ?>"<?php echo $older ? ' rel="nofollow"' : false; ?>>older</a>
<?php } ?>
</div>
<?php } ?>
<div class="t-center px-16 pb-27">
<form name="namespace" action="<?php echo BASE_URL; ?>" method="GET">
<input class="p-8" type="text" name="q" value="<?php echo ($query ? $query : ''); ?>" placeholder="key, value, block, ns, txid" autocomplete="off" />
<!--<button class="p-8 cursor-pointer" type="submit">Search</button>-->
</form>
</div>
<div class="t-center px-16 pb-27">
<?php if (!$tx && !$page) { ?>
<div class="pb-16 f-s-12"><a href="<?php echo BASE_URL; ?><?php echo ($query ? '?q=' . $query . '&rss' : ($ns ? $ns . '/rss' : 'rss')); ?>" rel="nofollow">RSS</a></div>
<?php } ?>
<div class="pb-16 f-s-12 c-1"><a href="https://github.com/kvazar-network/webapp">KVAZAR Webapp</a> is the content exploring platform for <a href="https://kevacoin.org">Kevacoin Blockchain</a>.</div>
<div class="f-s-12 c-1">Sources distributed under the MIT License. Ownership of all content belongs to the authors.</div>
</div>
</body>
</html>

2
public/robots.txt

@ -1,2 +0,0 @@
User-Agent: *
Sitemap: /sitemap.xml

21
public/rss.phtml

@ -1,21 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel>
<atom:link href="<?php echo BASE_URL; ?><?php echo ($ns ? $ns . '/rss' :
($query ? '?q=' . $query . '&amp;rss' : 'rss')); ?>" rel="self" type="application/rss+xml"></atom:link>
<title>KVAZAR - <?php echo ($namespaceValue ? $namespaceValue :
($namespaceHash ? $namespaceHash :
($query ? 'SEARCH - ' . $query : false))); ?></title>
<description>Observe Kevacoin Universe</description>
<link><?php echo BASE_URL; ?><?php echo ($ns ? $ns : ($query ? '?q=' . $query : false)); ?></link>
<?php foreach ($data as $item) { ?>
<item>
<title><?php echo $item['key']; ?></title>
<guid><?php echo BASE_URL; ?><?php echo $item['txid']; ?></guid>
<pubDate><?php echo $item['time']; ?></pubDate>
<description><?php echo $item['value']; ?></description>
<link><?php echo BASE_URL; ?><?php echo $item['txid']; ?></link>
</item>
<?php } ?>
</channel>
</rss>

0
cache/index.html → src/Controller/.gitignore vendored

11
src/Kernel.php

@ -0,0 +1,11 @@
<?php
namespace App;
use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
use Symfony\Component\HttpKernel\Kernel as BaseKernel;
class Kernel extends BaseKernel
{
use MicroKernelTrait;
}

58
symfony.lock

@ -0,0 +1,58 @@
{
"symfony/console": {
"version": "7.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "5.3",
"ref": "da0c8be8157600ad34f10ff0c9cc91232522e047"
},
"files": [
"bin/console"
]
},
"symfony/flex": {
"version": "2.4",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "1.0",
"ref": "146251ae39e06a95be0fe3d13c807bcf3938b172"
},
"files": [
".env"
]
},
"symfony/framework-bundle": {
"version": "7.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "7.0",
"ref": "6356c19b9ae08e7763e4ba2d9ae63043efc75db5"
},
"files": [
"config/packages/cache.yaml",
"config/packages/framework.yaml",
"config/preload.php",
"config/routes/framework.yaml",
"config/services.yaml",
"public/index.php",
"src/Controller/.gitignore",
"src/Kernel.php"
]
},
"symfony/routing": {
"version": "7.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "7.0",
"ref": "21b72649d5622d8f7da329ffb5afb232a023619d"
},
"files": [
"config/packages/routing.yaml",
"config/routes.yaml"
]
}
}
Loading…
Cancel
Save