Siberia PHP Framework

Status
Not open for further replies.

MayoMayn

BestDev
Oct 18, 2016
1,423
683
What is Siberia?
Siberia is a micro PHP framework built for web developer enthusiasts, that love to code their own back-end, but at the same time can't bother to code another 100+ features.

It includes features as:
  • MVC
  • Class autoloader by defined namespaces with Composer
  • MongoDB wrapper
  • PDO wrapper
  • Encrypted session control
  • Storage
  • Models
  • Requests
  • CSRF validation
  • Ready to go with ajax
  • VPN / Proxy / Hosting detection
  • Authenticator
  • API

Website is currently under construction:


#UPDATES

  • Added Git Repository:
  • Added Composer Package

Code Snippets of usage:
index.php
PHP:
define('__ROOT__', dirname(__FILE__));
// Require composer autoload
require_once __DIR__ . '/vendor/autoload.php';
// Require app autoload
$class = new Siberia\Autoload();
// Require external website settings
require_once __DIR__ . '/App/Config/System.php';

$app = $class->get('Siberia\Kernel\App');
$app->init();

User Model
PHP:
namespace Siberia\App\Model;
use Siberia\Database\Mongo;

class User
{

    protected $users;

    public function __construct()
    {
        $this->users = Mongo::select('Users');
    }

    public function nameTaken($user)
    {
        $result = $this->users->count(['username' => $user]);

        return ($result > 0);
    }

    public function emailTaken($email)
    {
        $result = $this->users->count(['mail' => $email]);

        return ($result > 0);
    }

}
 
Last edited:

Seriosk

Programmer;
Oct 29, 2016
256
105
Very simple to use, even for noobs. 10/10 bro, looking forward to creating good things on this.
 

MayoMayn

BestDev
Oct 18, 2016
1,423
683
Very simple to use, even for noobs. 10/10 bro, looking forward to creating good things on this.
Ty man, not quite finished yet, still need to implement some features, add the existing ones to the list, and create a documentation :D
 

MayoMayn

BestDev
Oct 18, 2016
1,423
683
Lovely! I love that you included the nginx.conf you nginx fanboy! Joking, looks great! :D
Sadly NGINX on Windows is just as slow as Apache and IIS lol, but thaks bro!
Miss my 0.000050 seconds render time :/
 
#UPDATES

app/Database/Mongo.php
Not entirely finished yet, still need some small changes.
PHP:
namespace Sentinel\Database;
use Sentinel\Kernel\Core;

class Mongo
{

    /**
     * @var string
     */
    public static $client, $db, $stmt, $log, $col;

    /**
     * Initialize connection to MongoDB Client
     * @return void
     */
    public function __construct()
    {
        if(!isset(static::$client) && !isset(static::$stmt) && !isset(static::$col)) {
            try {
                // Parse the config file
                $ini = Core::getConfig();
                self::$log = $ini['db_log'];
                // Initialize new connection
                static::$client = new \MongoDB\Client('mongodb://'.$ini['db_username'].':'.$ini['db_password'].'@'.$ini['db_cluster'].':'.$ini['db_port'].',cluster0-shard-00-01-q1ipf.mongodb.net:'.$ini['db_port'].',cluster0-shard-00-02-q1ipf.mongodb.net:'.$ini['db_port'].'/'.$ini['db_name'].'?ssl='.$ini['db_ssl'].'&replicaSet='.$ini['db_replica'].'&authSource='.$ini['db_auth']);
                // Set the default database
                static::$db = static::$client->{$ini['db_name']};
            } catch(Exception $e) {
                self::log($e->getMessage());
            }
        } else {
            return self::current();
        }
    }

    public static function current()
    {
        if(isset(static::$stmt))
            return static::$stmt;
        elseif(isset(static::$col))
            return static::$col;
        elseif(isset(static::$db))
            return static::$db;
        else
            return static::$client;
    }

    /**
     * Find or create database
     * @param database to create
     * @return bool
     * @throws Exception
     */
    public static function createDatabase($name)
    {
        try {
            if(empty($name))
                self::log("You must provide a name to create a database.");

            return (isset(static::$client) ? static::$db = static::$client->{$name} : false);
        } catch(Exception $e) {
            self::log($e->getMessage());
        }
    }

    /**
     * Delete a database
     * @param database to drop
     * @return bool
     */
    public static function dropDatabase($name)
    {
        try {
            if(empty($name))
                self::log("You must provide a name to drop a database.");

            return (isset(static::$client) ? static::$client->dropDatabase($name) : false);
        } catch(Exception $e) {
            self::log($e->getMessage());
        }
    }

    /**
     * Return an array with current available databases
     * @return array
     * @throws Exception
     */
    public static function listDatabases($return_array = false)
    {
        try {
            if(static::$client) {
                $list = static::$client->listDatabases();
                if(!$return_array) {
                    foreach($list as $database) {
                        var_dump($database);
                    }
                } else {
                    return $list;
                }
            }
            return false;
        } catch(Exception $e) {
            self::log($e->getMessage());
        }
    }

    /**
     * Create new collection
     * @param collection name and options
     * @return object
     * @throws Exception
     */
    public static function createCollection($name, array $options = [])
    {
        try {
            if(empty($name))
                self::log("New creation of collection is missing a name");

            return (isset(static::$db) ? static::$db->createCollection($name, $options) : false);
        } catch(Exception $e) {
            self::log($e->getMessage());
        }
    }

    /**
     * Drop a database collection
     * @param collection
     * @return bool
     */
     public static function dropCollection($name)
     {
        try {
            return (isset(static::$db) ? static::$db->dropCollection($name) : false);
        } catch(Exception $e) {
            self::log($e->getMessage());
        }
     }

     /**
     * Drop a database collection
     * @return Object
     * @throws Exception
     */
     public static function listCollections()
     {
        try {
            return (isset(static::$db) ? static::$db->listCollections() : false);
        } catch(Exception $e) {
            self::log($e->getMessage());
        }
     }

     /**
      * Select database collection to use
      * @param Collection
      * @return Object
      * @throws Exception
      */
     public static function select($name)
     {
        try {
            (isset(static::$db) ? static::$col = static::$db->{$name} : false);
            return new static;
        } catch(Exception $e) {
            self::log($e->getMessage());
        }
     }

     public static function findAll(array $filter = [], array $options = [])
     {
       try {
            return (isset(static::$col) ? static::$stmt = static::$col->find($filter, $options) : false);
            //return new static;
        } catch(Exception $e) {
            self::log($e->getMessage());
        }
     }

     public static function find(array $filter = [])
     {
        try {
            (isset(static::$col) ? static::$stmt = static::$col->findOne($filter) : "Collection not chosen.");
            return new static;
        } catch(Exception $e) {
            self::log($e->getMessage());
        }
     }

     /**
      *
      */
    public static function insert(array $data = [])
    {
        try {
            return (isset(static::$col) ? static::$stmt = static::$col->insertOne($data) : false);
            //return new static;
        } catch(Exception $e) {
            self::log($e->getMessage());
        }
    }

    public static function insertMany(array $data = [])
    {
        try {
            return (isset(static::$col) ? static::$stmt = static::$col->insertMany($data) : false);
            //return new static;
        } catch(Exception $e) {
            self::log($e->getMessage());
        }
    }

    public static function updateAll($filter, $update, array $options = [])
    {
        try {
            return (isset(static::$col) ? static::$stmt = static::$col->updateMany($filter, $update, $options) : false);
        } catch(Exception $e) {
            self::log($e->getMessage());
        }
    }

    public static function update($filter, $update, array $options = [])
    {
        try {
            return (isset(static::$col) ? static::$stmt = static::$col->updateOne($filter, $update, $options) : false);
        } catch(Exception $e) {
            self::log($e->getMessage());
        }
    }

    public function replace($filter, $replacement, array $options = [])
    {
        try {
            return (isset(static::$col) ? static::$stmt = static::$col->replaceOne($filter, $replacement, $options) : false);
        } catch(Exception $e) {
            self::log($e->getMessage());
        }
    }

    public function delete($filter, array $options = [])
    {
        try {
            return (isset(static::$col) ? static::$stmt = static::$col->deleteOne($filter, $options) : false);
        } catch(Exception $e) {
            self::log($e->getMessage());
        }
    }

    public function deleteMany($filter, array $options = [])
    {
        try {
            return (isset(static::$col) ? static::$stmt = static::$col->deleteMany($filter, $options) : false);
        } catch(Exception $e) {
            self::log($e->getMessage());
        }
    }
 
    /**
     * Get count of how many rows has been inserted
     * @return string
     * @throws Exception
     */
    public static function insertedCount()
    {
        try {
            return (isset(static::$stmt) ? static::$stmt->getInsertedCount() : false);
        } catch(Exception $e) {
            self::log($e->getMessage());
        }
    }

    /**
     * Get last inserted ID
     * @var string
     * @return result
     */
    public static function insertedId()
    {
        try {
            return (isset(static::$stmt) ? static::$stmt->getInsertedId() : false);
        } catch(Exception $e) {
            self::log($e->getMessage());
        }
    }

    public static function modifiedCount()
    {
        try {
            return (isset(static::$stmt) ? static::$stmt->getModifiedCount() : false);
        } catch(Exception $e) {
            self::log($e->getMessage());
        }
    }

    public static function matchedCount()
    {
        try {
            return (isset(static::$stmt) ? static::$stmt->getMatchedCount() : false);
        } catch(Exception $e) {
            self::log($e->getMessage());
        }
    }

    public static function count()
    {
        try {
            return (isset(static::$stmt) ? static::$stmt->count() : 0);
        } catch(Exception $e) {
            self::log($e->getMessage());
        }
    }

    /**
     * Log errors instead of outputting them.
     * @var array
     * @param array
     * @return result
     */
     public static function log($data)
     {
        // Set log file
        $log = __DIR__ . '/../utilities/logs/' . self::$log;
        // Check if file exists to receive content
        $content = file_get_contents($log) . "\r\n";
        // Set new content
        $content .= date('Y-m-d H:i:s') . " [error]\r\n" . $data . "\r\n";
        // Write content
        file_put_contents($log, $content);
        // Throw error
        die("A MongoDB error occurred, please contact the webmaster.");
     }

}


app/Security/CSRF.php
PHP:
namespace Sentinel\Security;
use Sentinel\Kernel\Core as Core;

class CSRF
{
     
    // $timespan token expiration time = 1 hour
    public static function check($csrf)
    {
        // Check if CSRF token exists
        if(!isset($_SESSION['csrf'])) {
            die('Missing CSRF session token.');
        }
        // Get valid token from session
        $hash = $_SESSION['csrf'];
        // CSRF validation using our Core decryption method
        if(Core::decrypt($csrf) !== Core::decrypt($hash)) {
            die("Invalid CSRF tokens");
        }
        // Unset token
        unset($_SESSION['csrf']);
        return true;
    }
 
    /**
     * CSRF token generation method. After generating the token, put it inside a hidden form field named $key.
     *
     * @param String $key The session key where the token will be stored. (Will also be the name of the hidden field name)
     * @return String The generated, base64 encoded token.
     */
    public static function generate()
    {
        // check if token has been validated
        if(!isset($_SESSION['csrf'])) {
            // Token generation using our Core encryption method
            $geo = Core::geoIP();
            $token = Core::encrypt($geo['latitude'] . $geo['ip'] . $_SERVER['HTTP_USER_AGENT'] . $geo['longitude']);
            // store the token in session
            $_SESSION['csrf'] = $token;
        }
        // return the token
        return $_SESSION['csrf'];
    }

}

static/js/core.min.js
ajax page loading using jquery history plugin
PHP:
(function($){
    var origContent = "";
    var content;

    var loadPage = function(url) {
        var body = $('div#content');
        //body.slideUp();
        footer('show');
        body.addClass("loader");
        $('.cssload-loader').show();

        if(url != "") {
            if(origContent == "") {
                origContent = $('div#content').html();
                var content = origContent;
            }
            // Get new page
            $.ajax({
                url: url,
                method: "GET"
            }).done(function(data) {
                //prettyPrint();
                content = $(data).filter('div#content').html();
                $('title').html($(data).filter('title').html());
            }).fail(function(xhr, ajaxOptions, thrownError) {
                console.log(xhr.status + ': ' + thrownError);
            });
        } else if(origContent != "") {
            content = origContent;
        }

        window.setTimeout(function() {
            $('.cssload-loader').hide();
            body.html(content);
            //body.slideDown();
            body.removeClass("loader");
        }, 1000);
    }

    $(document).ready(function() {
        $.history.init(loadPage);
        $('a[rel="load"]').click(function(e) {
            e.preventDefault();
            var url = $(this).attr('href');
            $.history.load(url);
            return false;
        });
    });
})(jQuery);
 

Brad

Well-Known Member
Jun 5, 2012
2,320
993
Moved this to the appropriate section. As it's not habbo related and could be used for anything.

Anyhow, good luck with this.
 

MayoMayn

BestDev
Oct 18, 2016
1,423
683
Website is currently under construction.
Thread will be updated as the documentation will.
 

Sledmore

Chaturbate Livestreamer
Staff member
FindRetros Moderator
Jul 24, 2010
5,199
3,934
Nice to see something like this! Website is looking really nice, looking forward to seeing it closer to completion.
 

MayoMayn

BestDev
Oct 18, 2016
1,423
683
Nice to see something like this! Website is looking really nice, looking forward to seeing it closer to completion.
Thanks man, so do I!
One of my top priorities for the website right now, is getting rid of the /#/ part in the url, since it fucks up some stuff, but seems like its impossible using the history.js plugin
 

MayoMayn

BestDev
Oct 18, 2016
1,423
683
Instead of posting snippets, is there a reason you don't throw this up on GitHub to get actual feedback and community involvement?
Still coding the documentation website and framework itself, but yeah, I've given it a thought about throwing it up on Github soon, and definitely make it composer compatible.

Sent from my SM-G928F using Tapatalk
 
#UPDATES
  • Added Git Repository:
  • Added Composer Package

Still need some fixing before it works correctly.
 
I'm pretty much out of ideas for what I could implement. So if any of you got any features that could be implemented, feel free to write them down!
 
#UPDATES
So yeah, basically I've used 5-6 hours researching, viewing different source code of popular frameworks as Laravel and Symfony to see what I could implement as features.
I'm gonna tear the MVC apart, add a Routing system, might code my own version of Blade Engine or just use Laravels, aswell as an Inversion of Control container and a really smart feature. Whatever database you might use, from mysql to mongodb, its all going to be used by the same wrapper, so you can easily switch or use different databases inside the same project.
Basically one of the many purposes of this framework, is to implement features that people use hours to research on, like restriction of a visitor, payment system, user authentication etc.
 
Basically a little preview of how the routing system is going.
It's gonna be a bit similar to Laravel's, but a bit different , as I like how they do it in production.
PHP:
<?php
use Siberia\Http\Route;

Route::get('/', 'Home@index');

Route::get('/docs', 'Docs@index');

// az means it will only allow input that match the regex "[a-z]++"
Route::get('/docs/database/[az:page]', 'Docs@database');
MVC has been removed for now.
Probably gonna implement the Blade Engine or something similar.
 
#UPDATES
I am finally getting closer at finishing the Router Class!
Basically here's how it works:
To set the default controller there will be called when the user visits certain pages:
PHP:
// This calls the index method in class App\Controllers\Home
Route::setIndex('Home');
// or
Route::get('/' 'Home@index');
// To an alternative you can set the default error method that will be called to show an error page to the user
// Again this will call the index method in class App\Controllers\Error
Route::setError('Error');
Here's the really fucking smart part if you compare this to Laravel:
e.g let's say you have several controllers that are just used to show certain contents or return a variable, you will not have to define the route, because the Router automatically finds the method based upon the exploding of the url like so:
=> Class = User, Method = Profile, Param = 3

You can also check for regex like so:
PHP:
// az will only allow the characters lowercase a to z
Route::get('/docs/database/[az:page]', 'Docs@database');

You can add your own regex to the router for easier management like so:
PHP:
Route::addMatchTypes([
          'AZ' => '[A-Z]++'
]);
 

Jaden

not so active
Aug 24, 2014
886
263
Make sure you're profiling your code... your framework can have all the convention features it wants but what really paid attention to in comparison to other frameworks is functionality to speed.
 

MayoMayn

BestDev
Oct 18, 2016
1,423
683
Make sure you're profiling your code... your framework can have all the convention features it wants but what really paid attention to in comparison to other frameworks is functionality to speed.
So far the speed couldn't really be improved except with the rendering of views.
Everything that has curl requests etc or whatsoever the results gets cached in a Storage folder for faster usage.
But well, there's nothing that cant be improved.
 
Last edited:

Weasel

👄 I'd intercept me
Nov 25, 2011
4,135
2,461
Could you please make 2 seperate threads, one for the releases (links to composer/git) and one specifically for development? This way every source available in CP can be found in one section.
 

MayoMayn

BestDev
Oct 18, 2016
1,423
683
Could you please make 2 seperate threads, one for the releases (links to composer/git) and one specifically for development? This way every source available in CP can be found in one section.
Sure thing! Thought about that too.

What section should it be in? Free Programs/Scripts?
 

MayoMayn

BestDev
Oct 18, 2016
1,423
683
Yep! After you did, I'll clean this topic of these comments.
Some times I get sick of Git repositories. I keep on getting the Github merge conflicts, when trying to do large pull requests.
 
Currently I'm looking for a decent template engine, and I've taken a look at Twig, Blade and Foil, but I'm incapable of deciding which one I should use.
If I cant decide I'm just gonna code one from scratch.

Any suggestions for another engine?
 
#UPDATES
Okay, so I finally got to implement a template engine.
It was between Blade or Twig, but when I tried to implement Blade it didn't go as well as I thought it might.
In the future there might be an option to switch between Blade or Twig, but for now it's going to be Twig.

Little preview of the Twig class used to implement the Twig Environment:
PHP:
namespace Siberia\View;
use Siberia\Kernel\App;

class Twig
{

    protected static $twig, $template;

    protected static $ext = ".html";

    protected static $resources = __ROOT__ . 'app/resources/views';

    public static function start()
    {
        $config = App::config('twig');
        $loader = new \Twig_Loader_Filesystem(static::$resources);
        static::$twig = new \Twig_Environment($loader, ($config['environment']) ? $config['environment'] : []);

        $globals = $config['globals'];
        if(!empty($globals)) {
            foreach($globals as $key => $value) {
                if(is_callable($value)) {
                    $value = call_user_func($value);
                }

                static::$twig->addGlobal($key, $value);
            }
        }

    }

    public static function setExtension($ext)
    {
        static::$ext = $ext;
    }

    public static function separate($path)
    {
        return str_replace(".", "/", $path);
    }

    public static function view($path, array $vars = [])
    {
        return print(static::$twig->render(self::separate($path) . static::$ext, $vars));
    }

    public static function load($path)
    {
        return static::$template = static::$twig->load(self::separate($path) . static::$ext);
    }

    public static function render(array $vars = [])
    {
        return print(static::$template->render($vars));
    }

    public static function renderBlock($name, array $vars = [])
    {
        return static::$template->renderBlock($name, $vars);
    }

    public static function content($view)
    {
        return file_get_contents(static::$resources . $view . static::$ext);
    }

}

And for the Twig config:
PHP:
use Siberia\Kernel\App;
return [
    'environment' => [
        'cache' => __ROOT__ . 'app/storage/cache/views', // Set to false or remove to disable caching
        'debug' => true                                  // Set to false or remove to disable debugging
    ],

    'globals' => [
        'url' => App::url()
    ]
];
 

Weasel

👄 I'd intercept me
Nov 25, 2011
4,135
2,461
It might be a stupid question, but why are you using static:: instead of self::?
 

MayoMayn

BestDev
Oct 18, 2016
1,423
683
It might be a stupid question, but why are you using static:: instead of self::?
Let's say we got a class that extends another class, which has a static property with the same name, it uses the one from the current class and not the extended one.
Well, it has just become a habit to me to use static over self, hehe, and it looks a lot cleaner if you ask me.

 
Status
Not open for further replies.

Users who are viewing this thread

Top