text:
php-sbcrud
==========
Sometimes it may be desired to develop web-based information systems, typically
using a relational database for storage. This library provides abstractions to
make developing such information systems more convenient.

The concepts of this library are built on top of the
[php-sblayout](https://github.com/svanderburg/php-sblayout) library to organize
layouts of web application pages and
[php-sbdata](https://github.com/svanderburg/php-sbdata) that takes care of
validating and displaying data elements.

More specifically, this package provides the following features:
* Data validation for input parameters
* Construction of master-detail pages
* Construction of CRUD pages
* State parameter propagation

Installation
============
This package can be embedded in any PHP project by using
[PHP composer](https://getcomposer.org). Add the following items to your
project's `composer.json` file:

```json
{
  "repositories": [
    {
      "type": "git",
      "url": "https://github.com/svanderburg/php-sbcrud.git"
    }
  ],

  "require": {
    "svanderburg/php-sbcrud": "@dev",
  }
}
```

and run:

```bash
$ composer install
```

Installing development dependencies
===================================
When it is desired to modify the code or run the examples inside this
repository, the development dependencies must be installed by opening
the base directory and running:

```bash
$ composer install
```

Usage
=====
This package contains a variety of features to make the development of web-based
information systems (typically using a relational DBMS as a backend) more
convenient.

Data validation for input parameters
------------------------------------
The purpose of the `php-sblayout` is to organize layouts. It uses the path
components in a URL to determine which page has been requested by the user and
automatically generates the requested page from static parts (that are the same
for any page of the application) and dynamic parts (that change for each
selected page).

A common feature for web-based information systems is that users are allowed to
change data (e.g. by providing GET/POST parameters or a path component). Input
provided by users cannot be trusted and must be checked for validity (e.g.
whether they do not exceed a maximum length, and whether they consist of the
right characters).

The `php-sblayout` leaves the responsibility of checking input parameters to
the user. The first use case of this library is to use the features of
`php-sbdata` to automatically check input parameters.

For example, we can create a trivial application whose main purpose is to
display the name of a user with an optional a custom greeting. For example, when
invoking the following URL:

```
http://localhost/check/index.php/name/Sander
```

The user should see:

```
Hello Sander
```

It is also possible to add an optional `greeting` parameter that specifies how
the caller is greeted (the default is: `Hello`). For example, by opening the
following URL:

```
http://localhost/check/index.php/name/Sander?greeting=Hi
```

The user should see:

```
Hi Sander
```

The prefix and name parameters are not allowed to be longer than 10 characters.

For example, the following request should return a bad request page because the
greeting is too long:

```
http://localhost/check/index.php/name/Sander?greeting=Averylonglonglongwelcome
```

We can map to the following URL: `/index.php/name` to a `MasterPage` (an
extension of the `DynamicContentPage` from the `php-sblayout` framework) by
overriding the class with the following properties:

```php
namespace Examples\Check\Model\Page;
use SBLayout\Model\Page\ContentPage;
use SBLayout\Model\Page\Content\Contents;
use SBData\Model\Value\Value;
use SBCrud\Model\Page\MasterPage;

class NamePage extends MasterPage
{
	public function __construct()
	{
		parent::__construct("Name", "name", new Contents("name.php"));
	}

	public function createParamValue(): Value
	{
		return new Value(true, 10);
	}

	public function createDetailPage(array $query): ?ContentPage
	{
		return new PrintNamePage();
	}
}
```

In the above class, we have specified the following properties:

* We construct a page with title: `Name` that uses the `name` identifier for
  the variable that stores the value of the path component (that is appended to
  the URL). The resulting value is stored in: `$GLOBALS["query"]["name"]`.
  It displays the `name.php` code snippet in the contents section. This snippet
  displays instructions to the user explaining how a name with a greeting can be
  displayed.
* The `createParamValue` method constructs a `Value` object that specifies how
  the `name` path component should be validated. In this case, it specifies that
  it needs to be a string with a maximum length of 10.
* The `createDetailPage` method constructs the sub page of this page -- the
  page that is responsible for consuming the path parameter and displaying the
  greeting to the user.

We can define the `PrintNamePage` class that is responsible for displaying
a greeting to the user as follows:

```php
namespace Examples\Check\Model\Page;
use SBLayout\Model\Page\Content\Contents;
use SBData\Model\ParameterMap;
use SBData\Model\Value\SaneStringValue;
use SBCrud\Model\Page\DetailPage;

class PrintNamePage extends DetailPage
{
	public function __construct()
	{
		parent::__construct("Print name", new Contents("name/printname.php"));
	}

	public function createRequestParameterMap(): ParameterMap
	{
		return new ParameterMap(array(
			"greeting" => new SaneStringValue(true, 10, "Hello")
		));
	}
}
```

The above class extends the `DetailPage` class (an extension of the
`StaticContentPage` of the `php-sblayout` framework) with the following
properties:

* We construct a page with title: `Print name` that displays the
  `name/printname.php` PHP snippet to display a greeting to the user.
* The `createRequestParameterMap` returns a `ParameterMap` that specifies how
  `$_REQUEST` parameters need to be validated. By using a `SaneStringValue`
  object, the `greeting` parameter is automatically sanitized (from trailing
  white spaces etc.) and is not allowed to be longer than 10 characters. The
  default greeting is: `Hello`.

The parameter values of path components can be accessed through the
`$GLOBALS["query"]` array whereas the request parameters can be accessed through
the `$GLOBALS["requestParameters"]` array. These variables should be used
instead of PHP's `$_REQUEST`, `$_GET`, and `$_POST`, whose values have not been
checked or sanitized.

For example, we can display the content page: `name/printname.php` as follows
to construct the greeting to the user:

```php
<p><?= $GLOBALS["requestParameters"]["greeting"]." ".$GLOBALS["query"]["name"] ?></p>
```

In case, any of the parameters is invalid, a `BadRequestException` is thrown and
the user gets automatically redirected to the `400` error page (that explains
the user why the request has failed).

We can attach the `NamePage` to an application layout as follows:

```php
use SBLayout\Model\Application;
use SBLayout\Model\Section\ContentsSection;
use SBLayout\Model\Section\MenuSection;
use SBLayout\Model\Section\StaticSection;
use SBLayout\Model\Page\HiddenStaticContentPage;
use SBLayout\Model\Page\PageAlias;
use SBLayout\Model\Page\StaticContentPage;
use SBLayout\Model\Page\Content\Contents;
use Examples\Check\Model\Page\NamePage;

$application = new Application(
	/* Title */
	"Print name",

	/* CSS stylesheets */
	array("default.css"),

	/* Sections */
	array(
		"header" => new StaticSection("header.php"),
		"menu" => new MenuSection(0),
		"contents" => new ContentsSection(true)
	),

	/* Pages */
	new StaticContentPage("Home", new Contents("home.php"), array(
		"400" => new HiddenStaticContentPage("Bad request", new Contents("error/400.php")),
		"404" => new HiddenStaticContentPage("Page not found", new Contents("error/404.php")),

		"home" => new PageAlias("Home", ""),
		"name" => new NamePage()
	))
);

\SBLayout\View\HTML\displayRequestedPage($application);
```

In the above code fragment, we have attached a `NamePage` object instance to the
`name` sub page in the application. Because `NamePage` inherits from
`MasterPage` (that indirectly inherits from `Page`) we can attach it as a sub
page to any page that we want.

Creating master and detail pages
--------------------------------
In addition to parameter checking, another important use case of this framework
is to facilitate the construction of *master* and *detail* pages. This use case
explains the rationale behind the naming of the page classes.

We have picked the name: `MasterPage` for pages that are supposed to display
collections of records, whereas a `DetailPage` is designed to display individual
records, that can be queried by providing a path component as a parameter.

For example, for a library system we may want to display a table of books by
opening the following URL:

```
http://localhost/index.php/books
```

The properties of an individual book can be displayed by appending a path
component as a parameter:

```
http://localhost/index.php/books/978-0131429383
```

The last path component: `978-0131429383` refers to the ISBN number of an
individual book.

We can construct a `BooksPage` (that is a sub class of `MasterPage`) as follows:

```php
namespace Examples\ReadOnly\Model\Page;
use PDO;
use SBLayout\Model\Page\Content\Contents;
use SBLayout\Model\Page\ContentPage;
use SBData\Model\Value\Value;
use SBCrud\Model\Page\MasterPage;

class BooksPage extends MasterPage
{
	public PDO $dbh;

	public function __construct(PDO $dbh)
	{
		parent::__construct("Books", "isbn", new Contents("books.php", "books.php"));
		$this->dbh = $dbh;
	}

	public function createParamValue(): Value
	{
		return new Value(true, 17);
	}

	public function createDetailPage(array $query): ?ContentPage
	{
		return new BookPage($this->dbh, $query["isbn"]);
	}
}
```

The above class has the following properties:

* It specifies a page with title: `Books` in which the appended path component
  value is stored in the `$GLOBALS["query"]["isbn"]` variable. It uses the
  `contents/books.php` PHP snippet to display a table with an overview of books,
  using the `controller/books.php` controller to query all books and
  constructing a `DBTable` from it.
* It specifies through the `createParamValue` method that the path component
  (`isbn`) has a maximum length of 17 characters.
* It constructs a detail page (a `BookPage` object) that displays an individual
  book by using the `isbn` parameter to query the properties of the requested
  book.

We can define the `BookPage` (a sub class of `DetailPage`) as follows:

```php
<?php
namespace Examples\ReadOnly\Model\Page;
use PDO;
use SBLayout\Model\PageNotFoundException;
use SBLayout\Model\Page\Content\Contents;
use SBCrud\Model\Page\DetailPage;
use Examples\ReadOnly\Model\Entity\Book;

class BookPage extends DetailPage
{
	public array $entity;

	public function __construct(PDO $dbh, string $isbn)
	{
		parent::__construct("Book", new Contents("books/book.php", "books/book.php"));

		$stmt = Book::queryOne($dbh, $isbn);
		if(($entity = $stmt->fetch()) === false)
			throw new PageNotFoundException("Cannot find book with ISBN: ".$isbn);

		$this->title = $entity["Title"];
		$this->entity = $entity;
	}
}
?>
```

The above class defines a constructor with the following properties:

* It creates a page with default title: `Book` and uses a dedicated controller
  and content page (both are named: `books/book.php`)
* It queries the individual book record and adjusts the page title to match the
  book title.
* In case that the book cannot be found, it throws a: `PageNotFoundException`.
  The `php-sblayout` framework will automatically redirect the user to the 404
  error page that displays the provided error message.

Because it is desired to have the ability to change the title of a page to match
an individual book title, every `DetailPage` (and hence every `BookPage`) is a
unique object instance. This is in contrast to most other `Page` instances
that are part of the `Application` object -- they are immutable singleton
instances.

Because it is desired to construct unique object instances for detail pages
explains why you must override the `createDetailPage` method of a `MasterPage`
-- it makes it possible to lazily construct unique instances of a detail page.

Creating CRUD pages
-------------------
The previous example only supports read operations. We may also want to give
the user the ability to make *modifications*, by implementing create, update,
and delete operations. To make this possible we need to extend our previous
master-detail URL convention with additional operations.

For modern web applications developed today, it is a common habit to facilitate
CRUD operations by implementing a REST API following a convention in which HTTP
operations are used in a specific way, for example:

* `GET /books`. Retrieves a collection of records
* `POST /books`. Inserts new records
* `GET /books/978-0131429383`. Retrieves the properties of an individual record
* `PUT /books/978-0131429383`. Updates the properties of an individual record
* `DELETE /books/978-0131429383`. Deletes the selected record

REST operations typically use JSON for the input and output of data.

In this framework, we cannot directly use these REST conventions because it aims
to be page-driven and the reduction of JavaScript usage to a minimum (for
non-essential functionality mostly). As a result, it avoids doing any JSON
transformations on the client-side. HTML can basically only transfer data by
making `GET` or `POST` requests through hyperlinks or forms.

This framework follows URL conventions that are close to REST, but instead of
using an HTTP operation, it uses a request parameter to determine the kind of
operation that needs to be executed (by default the parameter name is:
`__operation`, but it can be changed to any other identifier by through the
`$operationParam` parameter). If no operation parameter is specified, the
framework assumes that the user invoked the read operation.

We can apply this convention to our books example as follows:

* `/index.php/books`. Retrieves and displays a collection of records
* `/index.php/books?__operation=add_book`. Shows a screen that the user can use
  to create a new record
* `/index.php/books?__operation=insert_book`. Inserts a provided book into the
  data store.
* `/index.php/book/978-0131429383`. Retrieves and displays an individual record.
  It also provides facilities (e.g. input fields) allowing the user to change
  the record.
* `/index.php/book/978-0131429383?__operation=update_book`. Updates the selected
  book.
* `/index.php/book/978-0131429383?__operation=delete_book`. Deletes the selected
  book.

The above URLs can be invoked both through HTTP `GET` and `POST` requests.

To extend the previous books example to give the user the ability to change
data, we must change the displayed pages for each operation. For example, when
opening the `/index.php/books` page we should see a table, but when requesting
`/index.php/books?__operation=add_book` then we should see an input form.

By inheriting from `CRUDMasterPage` and `CRUDDetailPage` rather than `MasterPage`
and `DetailPage`, we can specify what content to display when an operation
parameter was specified.

For example, the following example changes the `BooksPage` to implement the
`add_book` and `insert_book` operations:

```php
namespace Examples\Full\Model\Page;
use PDO;
use SBLayout\Model\Page\ContentPage;
use SBLayout\Model\Page\Content\Contents;
use SBData\Model\Value\Value;
use SBCrud\Model\Page\CRUDMasterPage;
use SBCrud\Model\Page\OperationPage;
use SBCrud\Model\Page\HiddenOperationPage;

class BooksPage extends CRUDMasterPage
{
	public PDO $dbh;

	public function __construct(PDO $dbh)
	{
		parent::__construct("Books", "isbn", new Contents("books.php", "books.php"), array(
			"add_book" => new OperationPage("Add book", new Contents("add_book.php", "add_book.php")),
			"insert_book" => new HiddenOperationPage("Insert book", new Contents("insert_book.php", "insert_book.php"))
		));
		$this->dbh = $dbh;
	}

	public function createParamValue(): Value
	{
		return new Value(true, 17);
	}

	public function createDetailPage(array $query): ?ContentPage
	{
		return new BookPage($this->dbh, $query["isbn"]);
	}
}
```

The most notable change in the above example is that we extend the `BooksPage`
class from `CRUDMasterPage` and that in the constructor we specify
`OperationPage`s that need to be displayed when an operation was provided as a
parameter:

* When the user specifies the `add_book` operation, the layout manager returns a
  controller that creates an empty form and content section that renders a form.
* The `insert_book` operation causes the layout manager to invoke a controller
  that inserts the record.

If no operation was specified, the page retains its original behaviour -- it
will simply use the controller and content page to display a table with an
overview of books.

Creating CRUD interfaces
------------------------
Although the above facilities make it possible to change the pages for every CUD
operation, specifying separate controllers and content pages for each operation
may be quite inconvenient.

For example, the `add_book`, `update_book` and the page that displays an
individual book (`/index.php/books/978-0131429383`) use the same `Form` to
display and validate the properties of a book

Furthermore, almost all non-read operations (with the exception of the books
master view) need to display an individual record.

All these requirements introduce quite a bit of code duplication.

A more convenient solution is to unify all controllers by creating a custom
`CRUDInterface` object that stores the implementation of all CRUD operation of
an object (such as a `Book`) in a central place:

```php
namespace Examples\Full\Model\CRUD;
use PDO;
use SBLayout\Model\Route;
use SBLayout\Model\Page\ContentPage;
use SBData\Model\Field\TextField;
use SBData\Model\Field\HiddenField;
use SBData\Model\Table\Anchor\AnchorRow;
use SBCrud\Model\RouteUtils;
use SBCrud\Model\CRUDForm;
use SBCrud\Model\CRUD\CRUDInterface;
use SBCrud\Model\Page\OperationParamPage;
use Examples\Full\Model\Entity\Book;

class BookCRUDInterface extends CRUDInterface
{
	public PDO $dbh;

	public Route $route;

	public OperationParamPage $currentPage;

	public CRUDForm $form;

	public function __construct(PDO $dbh, Route $route, OperationParamPage $currentPage)
	{
		parent::__construct($currentPage);
		$this->dbh = $dbh;
		$this->route = $route;
		$this->currentPage = $currentPage;
	}

	private function constructForm(): CRUDForm
	{
		return new CRUDForm(array(
			"isbn" => new TextField("ISBN", true, 20),
			"Title" => new TextField("Title", true, 40),
			"Author" => new TextField("Author", true, 40)
		), $this->operationParam);
	}

	private function viewBook(): void
	{
		$this->form = $this->constructForm();
		$this->form->importValues($this->currentPage->entity);
		$this->form->setOperation("update_book");
	}

	private function addBook(): void
	{
		$this->form = $this->constructForm();
		$this->form->setOperation("insert_book");
	}

	private function insertBook(): void
	{
		$this->form = $this->constructForm();
		$this->form->importValues($_REQUEST);
		$this->form->checkFields();

		if($this->form->checkValid())
		{
			$book = $this->form->exportValues();
			Book::insert($this->dbh, $book);

			header("Location: ".RouteUtils::composeSelfURL()."/".rawurlencode($book['isbn']));
			exit();
		}
	}

	private function updateBook(): void
	{
		$this->form = $this->constructForm();
		$this->form->importValues($_REQUEST);
		$this->form->checkFields();

		if($this->form->checkValid())
		{
			$book = $this->form->exportValues();
			$isbn = $GLOBALS["query"]["isbn"];
			Book::update($this->dbh, $book, $isbn);

			header("Location: ".$this->route->composeParentPageURL($_SERVER["SCRIPT_NAME"])."/".rawurlencode($book['isbn']));
			exit();
		}
	}

	private function deleteBook(): void
	{
		$isbn = $GLOBALS["query"]["isbn"];
		Book::remove($this->dbh, $isbn);
		header("Location: ".$this->route->composeParentPageURL($_SERVER["SCRIPT_NAME"]).AnchorRow::composePreviousRowFragment());
		exit();
	}

	protected function executeCRUDOperation(?string $operation): void
	{
		if($operation === null)
			$this->viewBook();
		else
		{
			switch($operation)
			{
				case "add_book":
					$this->addBook();
					break;
				case "insert_book":
					$this->insertBook();
					break;
				case "update_book":
					$this->updateBook();
					break;
				case "delete_book":
					$this->deleteBook();
					break;
			}
		}
	}
}
```

The above class creates an interface that captures all CRUD operations for
`Book`s in a central place:

* The only mandatory method that a `CRUDInterface` sub class needs to implement
  is: `executeCRUDOperation` that decides which operation to execute based on
  the specified operation parameter. If an operation parameter is provided, it
  invokes the appropriate CRUD operation. If no operation was specified (`null`),
  it invokes the view operation.
* Every operation is implemented as a separate method to keep the code clean.
* Reuse of the same `Form` is made possible by using the `constructForm` method.
  In the above example, we use `CRUDForm` (that is a simple wrapper over the
  `Form` class in the `php-sbdata` framework) that makes it convenient to specify
  which CRUD operation needs to be executed.
* To safely refer to the self URL, we use a wrapper function named:
  `RouteUtils::composeSelfURL()` rather than PHP's unsafe `$_SERVER["PHP_SELF"]`
  that unescapes special characters.

The above class makes it possible to write a unified controller for all
book-related operations (`controllers/books/book.php`):

```php
use Examples\Full\Model\CRUD\BookCRUDInterface;

global $crudInterface, $dbh, $route, $currentPage;

$crudInterface = new BookCRUDInterface($dbh, $route, $currentPage);
$crudInterface->executeOperation();
```

The above controller will simply instantiate the `BookCRUDInterface` and
executes the requested operation.

Furthermore, since all operation pages need to display an individual book, we
can also use the same content page for all book operations
(`contents/books/book.php`):

```php
global $route, $crudInterface;

\SBLayout\View\HTML\displayBreadcrumbs($route);
\SBData\View\HTML\displayEditableForm($crudInterface->form);
```

The above content section displays breadcrumbs (showing the route that user
followed to open the page), and the form with the requested book data.

We can can wrap the above controller and content sections in a wrapper called
`BookContents`:

```php
namespace Examples\Full\Model\Page\Content;
use SBLayout\Model\Page\Content\Contents;

class BookContents extends Contents
{
	public function __construct()
	{
		parent::__construct("books/book.php", "books/book.php");
	}
}
```

and simplify the implementation of the `BooksPage` as follows:

```php
namespace Examples\Full\Model\Page;
use PDO;
use SBLayout\Model\Page\ContentPage;
use SBLayout\Model\Page\Content\Contents;
use SBData\Model\Value\Value;
use SBCrud\Model\Page\CRUDMasterPage;
use SBCrud\Model\Page\OperationPage;
use SBCrud\Model\Page\HiddenOperationPage;
use Examples\Full\Model\Page\Content\BookContents;

class BooksPage extends CRUDMasterPage
{
	public PDO $dbh;

	public function __construct(PDO $dbh)
	{
		parent::__construct("Books", "isbn", new Contents("books.php", "books.php"), array(
			"add_book" => new OperationPage("Add book", new BookContents()),
			"insert_book" => new HiddenOperationPage("Insert book", new BookContents())
		));
		$this->dbh = $dbh;
	}

	public function createParamValue(): Value
	{
		return new Value(true, 17);
	}

	public function createDetailPage(array $query): ?ContentPage
	{
		return new BookPage($this->dbh, $query["isbn"]);
	}
}
```

In the above example, all operation pages refer to the same contents:
`BookContents` that always displays the same controller and content sections.
Similarly, the `BookPage` that manages the operations of an individual book also
only need to refer to `BookContents`.

State parameter propagation
---------------------------
For master pages (that typically display collections of records), it is often
desired to perform stateful operations on the requested data collection. For
example, we may want to support *pagination* -- if the collection of data is
large we may want to reduce network bandwidth by dividing it into *pages* of a
fixed size (e.g. 20 records) and only display one page at the time.

For example, by adding pagination support, we may be able to view the first 20
book records with:

```
/index.php/books?page=0
```

and the next 20 with:

```
/index.php/books?page=1
```

Moreover, we may also want to make the ordering of the records configurable or
allow a user to filter data by providing query parameters.

When performing a CRUD operation from an altered master page and returning back
to that page from a detail page, knowledge about the state needs to be retained.
Not retaining this state provides a suboptimal user experience. For example, if
previous state is not retained, a user always gets redirected to the first page
after deleting a record, which is undesirable.

To retain knowledge about the state of parent pages, all `requestParameters` are
transitive -- sub pages retain the knowledge about the request parameters of
their parent pages. As a result, it is recommended that sub pages do not pick the
same parameter names as any of their parent pages.

When opening a sub page, it will also automatically parse the request parameters
of all their parents. As a result, the breadcrumbs feature still remembers the
settings of any of its parent pages.

There is one requirement imposed on developers to allow this to state retention
feature to work -- when a page needs to invoke the URL of any of its sub pages, it
also needs to propagate its request parameter values.

So, for example, when it is desired to open an individual book page, it may be
tempting to generate a URL relative the current URL:

```php
$subPageUrl = RouteUtils::composeSelfURL()."/".rawurlencode($isbn);
```

The downside is that opening the link above loses the knowledge of the state of
the current and any parent page.

To automatically propagate all request parameters, you can use the following
function call instead:

```php
use SBCrud\Model\RouteUtils;

$subPageUrl = RouteUtils::composeSelfURLWithParameters(null, "/".rawurlencode($isbn));
```

The above function call composes a URL relative to itself and automatically
propagates all request parameters.

Likewise, to compose a URL relative to the parent URL, you should use:
`RouteURL::composePreviousURLWithParameters()`.

There is a penalty for propagting state parameters -- due to parameter
propagation, there are multiple URLs that represent the same output. Having
multiple URLs that represent the same content may confuse search engines. To
clear up that confusion, a page will always output a canonical HTTP header that
tells the requester the URL without all propagated parameters:

```
Link: <http://localhost/paged/index.php/books>; rel="canonical"
```

Operation pages are never supposed to be indexed by search engines. As a result,
they emit the following HTTP header:

```
X-Robots-Tag: noindex, nofollow
```

Implementing pagination
-----------------------
It is quite common that we need to provide access to large collections of data.
For an optimal user experience, it is typically better to only display portions
of data. As a result, *pagination* is very common feature that needs to be
implemented. This framework contains a number of utilities to make that process
easier.

The following example revises the `BooksPage` class to accept a `page` parameter
that specifies the page in the data set that needs to be displayed:

```php
namespace Examples\Full\Model\Page;
use PDO;
use SBLayout\Model\Page\ContentPage;
use SBLayout\Model\Page\Content\Contents;
use SBData\Model\ParameterMap;
use SBData\Model\Value\Value;
use SBData\Model\Value\PageValue;
use SBCrud\Model\Page\CRUDMasterPage;
use SBCrud\Model\Page\OperationPage;
use SBCrud\Model\Page\HiddenOperationPage;
use Examples\Full\Model\Page\Content\BookContents;

class BooksPage extends CRUDMasterPage
{
	public PDO $dbh;

	public function __construct(PDO $dbh)
	{
		parent::__construct("Books", "isbn", new Contents("books.php", "books.php"), array(
			"add_book" => new OperationPage("Add book", new BookContents()),
			"insert_book" => new HiddenOperationPage("Insert book", new BookContents())
		));
		$this->dbh = $dbh;
	}

	public function createParamValue(): Value
	{
		return new Value(true, 17);
	}

	public function createRequestParameterMap(): ParameterMap
	{
		return new ParameterMap(array(
			"page" => new PageValue()
		));
	}

	public function createDetailPage(array $query): ?ContentPage
	{
		return new BookPage($this->dbh, $query["isbn"]);
	}
}
```

In the above example, the page has implemented a method:
`createRequestParameterMap()` that returns a map with GET parameters that need
to be checked. The `page` parameter can be used for querying a page. It is
checked for a valid page number (a value that is 0 or higher).

The `page` request parameter can be used to construct a query that queries the
requested sub set of data:

```php
$table = new DBTable(array(
	"isbn" => new KeyLinkField("ISBN", $composeBookLink, true),
	"Title" => new TextField("Title", true),
	"Author" => new TextField("Author", true)
), array(
	"Delete" => new Action($deleteBookLink)
));

$pageSize = 20;

$table->setStatement(Book::queryPage($dbh, (int)($GLOBALS["requestParameters"]["page"]), $pageSize));
```

In the above example, we construct a `DBTable` object. The PDO statement that
fetches the data uses the `$GLOBALS["requestParameter"]["page"]` to select the
requested data page.

When a data set is divided in pages, it is typically also desired to display a
navigation bar allowing the user to conveniently navigate between them. We can
create a `Pager` object to make this possible:

```php
use SBCrud\Model\Pager;

global $dbh, $pageSize;

$queryNumOfBookPagePages = function (PDO $dbh, int $pageSize): int
{
	return ceil(Book::queryNumOfBooks($dbh) / $pageSize);
};

$pager = new Pager($dbh, $pageSize, $queryNumOfBookPages);
```

In the above example we create a `Pager` object with the following properties:

* It needs to work with a data collection. In this particular example, we use a
  database connection handler: `$dbh`, but it can be any kind of object.
* The second parameter refers to the `$pageSize`: the maximum amount of records
  to be displayed on a single page. In the above example, that number is: `20`
* The last parameter: `$queryNumOfBookPages` refers to a function that
  determines the amount of pages. It the above example, that number is derived
  from the amount of books stored in the database. The parameters of the
  callback function: `$dbh` and `$pageSize` refer to the parameters that were
  passed to the `Pager` constructor.
* It is also possible to configure the labels and the name of the request
  parameter (which defaults to `page`). These parameters are not shown in the
  example.

We can display a navigation bar from the above pager object as follows:

```php
\SBCrud\View\HTML\displayPagesNavigation($pager);
```

Displaying operation toolbars
-----------------------------
Another common use case is to display a toolbar that exposes the available CRUD
operations of an individual record or any related records that are exposed as
parent pages.

A operation toolbar can be generated from the current page route as follows:

```php
global $route;

\SBCrud\View\HTML\displayOperationToolbar($route);
```

A generated toolbar section is very similar to generating an embedded menu
section in the php-sblayout framework:

* A toolbar displays visible operation pages only. It leaves out operation pages
  that are declared invisible (such as objects that are instances of the
  `HiddenOperationPage` class) or inaccessible.
* It also displays menu items in a custom way if specified (through the
  `menuItem` property)
* Moreover, it is also possible to style the toolbar and the hyperlinks in such
  a way that they appear as buttons

Examples
========
This package contains the previously described examples that can be found in the
`examples/` sub folder:

* `check` contains the example that shows how to check the validity of input
  parameters
* `readonly` shows a read-only book application example that demonstrates how
  to create master and detail pages
* `full` shows a full CRUD book example that also provides the user the ability
  to change data.
* `paged` extends the previous example with pagination support. It uses state
  parameter propagation methods to retain knowledge about the pagination setting.

API documentation
=================
This package includes API documentation that can be generated with
[Doxygen](https://www.doxygen.nl):

```bash
$ doxygen
```

License
=======
The contents of this package is available under the
[Apache Software License](http://www.apache.org/licenses/LICENSE-2.0.html)
version 2.0

repository: svanderburg/php-sbcrud

repo_name: svanderburg/php-sbcrud


text:
# Features
 - Simple drag to move
 - Simple drag to resize
 - Wheel for all sides size increments/decrement
 - Cool outline style drag move
 - Readable code(kind of)

# Installation
Xlib is the only dependency
```
make
make install
```

# Keymaps?
Nah, speration of WM and hotkey daemon give user a very clear seperation and more managable configuration.

# Thanks
[sowm](https://github.com/dylanaraps/sowm) by dylanaraps

[catwm](https://github.com/pyknite/catwm) by pyknite

license: MIT

repository: SeungheonOh/Wind

branch_name: refs/heads/master

extension: md

license_type: permissive

repo_name: SeungheonOh/Wind


text:
# DAAY-mall

---

## Deployed Link

[DAAY-mall Frontend website](https://daay-mall-app.netlify.app/)
[DAAY-mall Backend Server](https://daaymall-401-project.herokuapp.com/)

---

## Web Application

DAAY-mall is an online platform for stores owners to display and sell their products for users all around the world in an **easy**, **efficient** and **secure** process. The website earns client’s trust with its robust system that verifies stores and a direct customers’ service that have a live chat with website admins offering a continuous feedback.

Users:

- Admins:
  * Verify stores, customers' service and manage payments and refunds.

- Owners:
  * Register their stores, add products, manage orders.

- Registered Users:
  * Add to cart and checkout (payment), reviews stores and products and have a favorite stores list and wish list.

- Public Users:
  * Navigate website to view stores and products.

**Minimum MVP**

- **Authentication features**:
  * Sign-up and sign-in with Facebook.
  * Sign-up and sign-in with Google.
  * Normal signup and sign in.

- **Store registration**:
o The user can add his own store to be registered and then to be verified by the admin (with the ability to shop from other stores).
o When the store is verified the user will be the admin (owner) of his store and he can add employees (for customer service, data entry).
o Their stores can be sub stores.
• Shop
o Each user will have their own cart to add items to.
o Users can search for specific stores or products.
o Users can chat with support agents if they have an inquiry.
o Users can pay online.
• Data Entry
o Add products to the store
• Owner
o Register stores (create)/update store’s info/data
o Add/update employees
o Add/update products to the store
o Chat with customers
o Delete stores

---

## Tools Used

Microsoft Visual Studio

- Node.js
- Express
- Socket.io

---

## Wireframes

  **Part 1 :** https://wireframe.cc/pro/pp/22d596ce5359155
  **Part 2 :** https://wireframe.cc/pro/edit/359450

  **1- Profile-page-same-user:**

  ![1-Profile-page-same-user](assets/1-Profile-page-same-user-2x.png)

  **2- Profile-page-another-user:**

  ![2-Profile-page-another-user](assets/2-Profile-page-another-user-2x.png)

  **3- Store-page-user:**
  ![3-Store-page-user](assets/3-Store-page-user-2x.png)

  **4- Homepage:**

  ![4-Homepage](assets/4-Homepage.png)

  **5- Store-page-owner:**

  ![5-Store-page-owner](assets/5-Store-page-owner-2x.png)

  **6- Product:**

  ![6-Product](assets/6-Product.png)

  **7- Search page:**

  ![7-Search-page](assets/7-Search-page.png)

  **8- Help-center:**

  ![8-Help-center](assets/8-Help-center.png)

  **9- Sign-up:**

  ![9-Sign-up](assets/9-Sign-up.png)

## Getting Started

Clone this repository to your local machine.

```
git clone https://github.com/YourRepo/YourProject.git
```

Once downloaded, you can either use the dotnet CLI utilities or Visual Studio 2017 (or greater) to build the web application.

```
cd DAAY-mall
`npm i`
```

Install all dependencies needed for the project.

```
Database
```

- explain how to use the database \*

```
cd YourRepo/YourProject
npm start
```

---

<!-- ## Usage

***[Provide some images of your app that shows how it can be used with brief description as title]***

### Overview of Recent Posts

![Overview of Recent Posts](https://via.placeholder.com/500x250)

### Creating a Post

![Post Creation](https://via.placeholder.com/500x250)

### Enriching a Post

![Enriching Post](https://via.placeholder.com/500x250)

### Viewing Post Details

![Details of Post](https://via.placeholder.com/500x250)

---------------------------

## Data Flow (Frontend, Backend, REST API)

***[Add a clean and clear explanation of what the data flow is. Walk me through it.]***
![Data Flow Diagram](/assets/img/Flowchart.png)

--------------------------- -->

## Auth/ask for store (UML)

![auth](/assets/umlauth.PNG)

## Data Model

### Overall Project Schema

**Description of the DB schema]**
![Database Schema](./assets/schemas.png)

---

## Authors

Yazan Alaiwah
Diana Al azzam
Anolla Haddad
Ahmed Abu samaan

---

branch_name: refs/heads/development

gha_language: JavaScript

gha_license_id: MIT


text:
# Back End Challenge

> A Back End engineer should be comfortable writing deployable server code, working with databases (SQL, noSQL, etc), and designing RESTful and sensible APIs.

## Clone this Repo

1. **Fork** this repository
2. **Clone into your fork** of this repository.
3. `git checkout -b [challenge-name/your-name]`
4. `cd Akkadu_Challenges/back-end-engineer/submissions`
5. `mkdir [your-name] && cd $_`
6. When your finished with the challenge, push your local code to your remote fork.
7. Open a pull request between your remote branch and our base repository.
8. Add a reviewer 👍🏽

## Choose a Challenge

- ✅ [**Transactions API**](./challenges/transactions-api.md)
  > An API to query, analyze, and filter user transaction data

### All Challenges Should Include

- 👾 Server code that can be deployed and run on a server
- 🛰 Publicly accessible APIs
- 📫 [Postman](https://www.postman.com/) API collection
- 🗄 Database with persistant data

*NOTE: Feel free to use boilerplates or starter code according to your preference (we would use [express-generator][express-generator], you can use whatever you're comfortable with, as long as the challenge is completed to the specification)*

## Open a PR

- Go to Github and [open a new pull request][open-pull-request] from your branch to master.
- Fill out the [pull request template][pull-request-template] and assign [Pterobyte][pterobyte] as a reviewer.
- I'll add my comments, deploy it, test it, and approve or request changes based on my experience.

If you have any questions regarding these challenges or have suggestions/feedback, feel free to [email me](mailto:jt@akkadu-team.com?subject=Akkadu%20Challenges%20Feedback) 🤓

Go forth and hammer out some bangin new web api! 🔨

[express-generator]: https://expressjs.com/en/starter/generator.html
[open-pull-request]: https://github.com/Akkadu/Akkadu_Challenges/compare
[pull-request-template]: https://github.com/Akkadu/Akkadu_Challenges/blob/master/.github/pull_request_template.md
[pterobyte]: https://github.com/Pterobyte


text:
---
layout: default
---

# 1996-02-22 - No Subject

## Header Data

From<EMAIL_ADDRESS>To: _N/A_

Message Hash: 1c7f0ad2ab7ecbaac98042dedffc9069dd8602c69ee04f058a2c91d8e0d72a6a

Message ID<EMAIL_ADDRESS>Reply To: _N/A_

UTC Datetime: 1996-02-22 11:35:56 UTC

Raw Date: Thu, 22 Feb 1996 19:35:56 +0800

## Raw message

```
{% raw  %}From<EMAIL_ADDRESS>Date: Thu, 22 Feb 1996 19:35:56 +0800
Subject: No Subject
Message-ID<EMAIL_ADDRESS>MIME-Version: 1.0
Content-Type: text/plain

IPG Sales<EMAIL_ADDRESS>wrote:

>  See my reply to Tim Phillip - it is checked extensively
>
> If the algorithm sucks, prove it - please read the messages back and

See my comment below.
[..]
> > [..]
> > > In general, you will find the kernel of the propgations consists of 64
> > > equation sets of the form:
> > >
> > >        Bi=(Bi+Ci MOD Di) Mod 256             Large prime numbers
> > >        ENCRYPTEXTi=OTP[Bi] XOR PLAINTEXTi    Encryption
> > >        OTP[Bi]=ENCRYPTEXTi                   Makes the OTP Dynamic
> >
> > Bah. Looks to me like simple garbling, only using a large stream.
> >
> > Encrypt a stream of zeros with that method, and you'll get repeated
> > strings of OTP[Bi]'s.  An unsophisticated high school student could
> > crack that.

{% endraw %}
```

## Thread

+ Return to [February 1996](/archive/1996/02)

+ Return to "[owner-cypherpunks@toad.com](/authors/ownercypherpunks_at_toad_com)"

+ 1996-02-22 (Thu, 22 Feb 1996 19:35:56 +0800) - No Subject -<EMAIL_ADDRESS>


text:
# Security Policy

## Supported Versions

Use this section to tell people about which versions of your project are
currently being supported with security updates.

| Version | Supported          |
| ------- | ------------------ |
| 1.0.4   | :white_check_mark: |
| 1.0.3   | :white_check_mark: |
| 1.0.2   | :white_check_mark: |
| 1.0.1   | :white_check_mark: |
| 1.0.0   | :white_check_mark: |
| < 1.0.0 | :x:                |

## Reporting a Vulnerability

You can report a vulnerability to rramirez -AT- rootedcon.com or just using a PR
on the repo directly.

Just contact me and I'll try to do my best to answer in the shortest period of
time.

repository: patowc/blueliv

gha_language: Python

repo_name: patowc/blueliv


text:
# Description

Simple controller for one or more status LEDs, controlled via USB CDC.
This implementation is for Adafruit NeoPixels.

# Usage

If needed, change the `PIXELS_PIN` define to set the datapin for the NeoPixels, and `PIXELS_NUM` to change the number of NeoPixels.
Upload the sketch to the Arduino.

Connect to the Arduino at 115200 baud, with eight databits, no parity and one stopbit.

Change the state of a NeoPixel by sending its index and the first letter of the state to set.
The NeoPixels are zero-indexed, so with 5 pixels the first NeoPixel is 0 and the last is 4.
The available states are:
- none: off
- working: pulsing white
- success: green
- fault: yellow
- error: red

Multiple states can be sent in one string, for example `0w1s2f3n`.

Note that Arduinos, by design, get reset every time you connect to its serial port, which will clear the current state of the NeoPixels.

repository: gnawybol/statuscube-arduino

repo_name: gnawybol/statuscube-arduino


text:
# AstEditor
A very simple WYSIWYG editor

# Requires
jQuery v3.6.0
Bootstrap 4.6

# How to use

### 1. Connect
Add this line to the end of the `body` tag
```
	<script type="text/javascript" src="https://raw.githubusercontent.com/andrew-astetik/AstEditor/main/AstEditor.js"></script>
```

### 2. Create a block for the editor
###### The first and easiest way
`<div ae__asteditor></div>`
###### The second and simply simple way
It's just an example: `<div id="editor"></div>`

### 3. Init your editor box (Skip this step if you chose the first way)
Initialize your editor block with the command: `AstEditor.newBox([jQuery object]);`

### 4. Done
To get the html generated by the editor, use: `AstEditor.getHtml([selector]);`
`selector` - is (string)"Editor block id" or (jQuery object)"Editor block"

### 5.

repository: andrew-astetik/AstEditor

branch_name: refs/heads/main

repo_name: andrew-astetik/AstEditor


text:
***

# Pitch Website

#### **Monday September 24 2020** ;

---

## Author
> By ** [Akumu Collins](https://github.com/Akumucollins)
 ** ;

***

## Description
>This application allows users to post one minute pitches and also allows other users who have signed up to comment and upvote or downvote a pitch. It also allows a person to signup to be able to access the functionalities of the application

---

## Live Link
[View Site](https://akumucollins-pitches.herokuapp.com)

***

## Setup/Installation Requirements
To get the code..
Cloning the repository:
  ```bash
 https://github.com/Akumucollins/Wise_Pitches.git
  ```
Move to the folder and install requirements
  ```bash
  cd Wise_Pitches
  pip install -r requirements.txt
  ```
Exporting Configurations
  ```bash
  export SQLALCHEMY_DATABASE_URI=postgresql+psycopg2://{User Name}:{password}@localhost/{database name}
  ```
Running the application
  ```bash
  python3.8 manage.py server
  ```
Testing the application
  ```bash
  python3.8 manage.py test
  ```
Open the application on your browser
```bash
<IP_ADDRESS>:5000
```
---

## Dependencies
>* python3.8
>* pip
>* virtualenv

***

# Technologies Used
>* Flask
>* Python.

***

## Specifications
| Behaviour | Input | Output |
| :---------------- | :---------------: | ------------------: |
| Load the page | **On page load** | Get all posts, Select login|
| Select login |  **Email**,**Password** |Redirect to Home page|
| Select SignUp| **Email**,**Username**,**Password** | Redirect to login|
| Select Login | **Username** and **password** | Redirect to page with all pitches based on categories and commenting section|
| Select comment button | **Comment** | Form that you input your comment|
| Select comment button | **Add Comment** | Form that you input your comment|
| Select comment button | **View Comment** | Redirect to all comments|
| Click on submit |  | Redirect to all comments tamplate with your comment and other comments|

---

## Support and Contact Information
> The application is an open-source product if you  want to improve it or include an event of a bug  contact this
><EMAIL_ADDRESS>.

***

## License
The project is [MIT](LICENSE) licensed


text:
[![Build Status](https://secure.travis-ci.org/haiwen/seafile-docker.png?branch=master)](http://travis-ci.org/haiwen/seafile-docker)

### About

- [Docker](https://docker.com/) is an open source project to pack, ship and run any Linux application in a lighter weight, faster container than a traditional virtual machine.

- Docker makes it much easier to deploy [a Seafile server](https://github.com/haiwen/seafile) on your servers and keep it updated.

- The base image configures Seafile with the Seafile team's recommended optimal defaults.

If you are not familiar with docker commands, please refer to [docker documentation](https://docs.docker.com/engine/reference/commandline/cli/).

### Getting Started

To login the seafile private registry:

```sh
docker login {pro-host}
```

You can see the private registry information on the [customer center](https://customer.seafile.com/downloads/)

To run the seafile server container:

```sh
docker run -d --name seafile \
  -e SEAFILE_SERVER_HOSTNAME=seafile.example.com \
  -v /opt/seafile-data:/shared \
  -p 80:80 \
  {pro-host}/seafileltd/seafile-pro:latest
```

Wait for a few minutes for the first time initialization, then visit `http://seafile.example.com` to open Seafile Web UI.

This command will mount folder `/opt/seafile-data` at the local server to the docker instance. You can find logs and other data under this folder.

### Put your licence file

If you have a `seafile-license.txt` licence file, simply put it in the folder `/opt/seafile-data/seafile/`. In your host machine:

```sh
mkdir -p /opt/seafile-data/seafile/
cp /path/to/seafile-license.txt /opt/seafile-data/seafile/
```

Then restart the container.

```sh
docker restart seafile
```

### More configuration Options

#### Custom Admin Username and Password

The default admin account is<EMAIL_ADDRESS>and the password is `asecret`. You can use a different password  by setting the container's environment variables:
e.g.

```sh
docker run -d --name seafile \
  -e SEAFILE_SERVER_HOSTNAME=seafile.example.com \
  -e<EMAIL_ADDRESS>\
  -e SEAFILE_ADMIN_PASSWORD=a_very_secret_password \
  -v /opt/seafile-data:/shared \
  -p 80:80 \
  {pro-host}/seafileltd/seafile-pro:latest
```

If you forget the admin password, you can add a new admin account and then go to the sysadmin panel to reset user password.

#### Let's encrypt SSL certificate

If you set `SEAFILE_SERVER_LETSENCRYPT` to `true`, the container would request a letsencrypt-signed SSL certificate for you automatically.

e.g.

```
docker run -d --name seafile \
  -e SEAFILE_SERVER_LETSENCRYPT=true \
  -e SEAFILE_SERVER_HOSTNAME=seafile.example.com \
  -e<EMAIL_ADDRESS>\
  -e SEAFILE_ADMIN_PASSWORD=a_very_secret_password \
  -v /opt/seafile-data:/shared \
  -p 80:80 \
  -p 443:443 \
  {pro-host}/seafileltd/seafile-pro:latest
```

If you want to use your own SSL certificate:
- create a folder `/opt/seafile-data/ssl`, and put your certificate and private key under the ssl directory.
- Assume your site name is `seafile.example.com`, then your certificate must have the name `seafile.example.com.crt`, and the private key must have the name `seafile.example.com.key`.

#### Modify Seafile Server Configurations

The config files are under `shared/seafile/conf`. You can modify the configurations according to [Seafile manual](https://manual.seafile.com/)

After modification, you need to restart the container:

```
docker restart seafile
```

#### Find logs

The seafile logs are under `/shared/logs/seafile` in the docker, or `/opt/seafile-data/logs/seafile` in the server that run the docker.

The system logs are under `/shared/logs/var-log`, or `/opt/seafile-data/logs/var-log` in the server that run the docker.

#### Add a new Admin

Ensure the container is running, then enter this command:

```
docker exec -it seafile /opt/seafile/seafile-server-latest/reset-admin.sh
```

Enter the username and password according to the prompts. You now have a new admin account.

### Directory Structure

#### `/shared`

Placeholder spot for shared volumes. You may elect to store certain persistent information outside of a container, in our case we keep various logfiles and upload directory outside. This allows you to rebuild containers easily without losing important information.

- /shared/db: This is the data directory for mysql server
- /shared/seafile: This is the directory for seafile server configuration and data.
- /shared/logs: This is the directory for logs.
    - /shared/logs/var-log: This is the directory that would be mounted as `/var/log` inside the container. For example, you can find the nginx logs in `shared/logs/var-log/nginx/`.
    - /shared/logs/seafile: This is the directory that would contain the log files of seafile server processes. For example, you can find seaf-server logs in `shared/logs/seafile/seafile.log`.
- /shared/ssl: This is directory for certificate, which does not exist by default.

### Upgrading Seafile Server

TO upgrade to latest version of seafile server:

```sh
docker pull {pro-host}/seafileltd/seafile-pro:latest
docker rm -f seafile
docker run -d --name seafile \
  -e SEAFILE_SERVER_LETSENCRYPT=true \
  -e SEAFILE_SERVER_HOSTNAME=seafile.example.com \
  -e<EMAIL_ADDRESS>\
  -e SEAFILE_ADMIN_PASSWORD=a_very_secret_password \
  -v /opt/seafile-data:/shared \
  -p 80:80 \
  -p 443:443 \
  {pro-host}/seafileltd/seafile-pro:latest
```

If you are one of the early users who use the `launcher` script, you should refer to [upgrade from old format](https://github.com/haiwen/seafile-docker/blob/master/upgrade_from_old_format.md) document.

### Troubleshooting

You can run docker commands like "docker logs" or "docker exec" to find errors.

```sh
docker logs -f seafile
# or
docker exec -it seafile bash
```

repository: haiwen/seafile-docker

gha_license_id: NOASSERTION

repo_name: haiwen/seafile-docker


text:
# ubux-test
A simple ecommerce app. You can see available store and its products. Use `plus button` to add a product to your cart.
### Installation

```
git clone git@github.com:shotozuro/UbuxTest.git
cd UbuxTest
yarn install
```
### Usage
This project is built using [Expo](https://expo.io). If you don't have Expo installed on your machine, you should [Install Expo](https://docs.expo.io/versions/latest/introduction/installation/) first.

#### Run the project
```
expo start
```

license: Unlicense

repository: shotozuro/UbuxTest

gha_license_id: Unlicense

repo_name: shotozuro/UbuxTest


text:
---
layout: post
title:  "Wyrmskin"
date:   2017-01-01
source: From the Arcane Archive
tags: [druid, sorcerer, level3, transmutation, hb]
---

**3rd-level transmutation**

**Casting Time**: 1 action

**Range**: Self

**Components**: V, M (a dragon scale)

**Duration**: Concentration, up to 1 hour

This spell transforms you into a dragon of the same color as the scale provided for the material component. The transformation lasts for the duration, or until you drop to 0 hit points or die.  Your game statistics are replaced by the wyrmling's statistics, though you retain your alignment and Intelligence, Wisdom, and Charisma scores. You lose the ability to cast spells in this form and the ability to use any class features that your draconic form could not feasibly perform. Your gear melds into the new form. You can't activate, use, wield, or otherwise benefit from any of your equipment.
At Higher Levels. Casting this spell using a 6th or 7th level spell slot allows you to transform into the young dragon of the dragon whose scale you provided as the material component for this casting. Casting this spell using an 8th or 9th level spell slot allows you to transform into the adult dragon of the dragon whose scale you provided as the material component for this casting.

repository: Teamdael/spellbook

extension: markdown

repo_name: Teamdael/spellbook


text:
Pico Admin Plugin by Kay Stenschke / www.coexec.com
===================================================

Version 2.0.1
-------------
* Bugfix: File paths were not resolved correctly on some servers
* Added meta attributes storage (title, description) and administration in a meta.php file, w/ an associative array, storing meta attributes for every image in folder
* Made assets list scrollable
* Extracted some helper methods into static helper classes

Version 2.0.0
-------------
* Added a guided tour of the administration's user interface
* Added simple translation handling and UI translations in english and german
* Made UI panels resizable
* Added assets manager:
  * browsing of /content/images
  * option to create directories
  * option to upload, download, rename and delete files and directories
  * automatic thumbs generation for images, thumb display on mouseover of files
* Removed unsaved observer / auto-saving
* Replaced EpicEditor by markItUp (faster, easier extensible)
* Added option to rename post files
* Added post info: filename of currently loaded post, with option to rename the file
* Added multi-level ability to tree: display, rename and delete directories, load and save nested posts
* Changed template for new pages: reduced attributes, added "Placing" attribute (requires pico_placing plugin)
* Extended pages listing to include 404 page in admin
* Improved Log-In: added auto-focus password field, added welcome splash w/ reload after successful login, to ensure Pico core (loaded before editor) knowing the log-in status
* Accelerated page load: reduced requests by implementing automatic merging of CSS files and JS files, merged icons into sprite
* Replaced icoMoon icon font by (FontAwesome) icons
* Extracted redundant code from actions into methods
* Integrated jQuery.min.js into assets delivered w/ the plugin (was: loaded via google CDN)
* Moved all global inline JavaScript into an external file, containing only one object in the global scope
* Added this changelog

Pico Editor Version 1.1 by Gilbert Pellegrom / www.dev7studios.com
------------------------------------------------------------------
This is the original plugin which the Pico Admin Plugin was refactored and extended into.


text:
---
layout: default
---

# 1997-09-14 - Re: unSAFE won't pass?

## Header Data

From: Declan McCullagh<EMAIL_ADDRESS>To: Will Rodger<EMAIL_ADDRESS>Message Hash: ad14313ace3fb14a193f8d79d490eee0f39199905b78bdc886c95b3e1663577f

Message ID<EMAIL_ADDRESS>Reply To<EMAIL_ADDRESS>UTC Datetime: 1997-09-14 19:55:20 UTC

Raw Date: Mon, 15 Sep 1997 03:55:20 +0800

## Raw message

```
{% raw  %}From: Declan McCullagh<EMAIL_ADDRESS>Date: Mon, 15 Sep 1997 03:55:20 +0800
To: Will Rodger<EMAIL_ADDRESS>Subject: Re: unSAFE won't pass?
In-Reply-To<EMAIL_ADDRESS>Message-ID<EMAIL_ADDRESS>MIME-Version: 1.0
Content-Type: text/plain

On Sun, 14 Sep 1997, Will Rodger wrote:

> It may make for good copy, but I think it's just fantasy to think the
> administration or their opponents, for that matter, will get what
> they want this year. Let them swarm. Who cares.
>
> At earliest, August of 1998 before anything passes - and even that is
> highly optimistic.

I agree with Will that we'll likely see shouting on the floor, but I'm
not as convinced on the timing.

Sure, it's incredibly unlikely that anything will pass both chambers this
year. But will it take 11 months? The sequence of events could look
something like this:

By late September, the Commerce committee will vote on SAFE. By
mid-October, the committee chairs should have worked out a compromise
package. This goes to the Rules committee, chaired by Solomon. Until last
week he vowed to block SAFE. Now he'd like, I'm told, to get the FBI's
version to the floor immediately. There are, however, only so many slots
on the suspension calendar.

It's conceivable the House could vote on the bill this year, especially if
they leave town later than anticipated and only if the version is the
FBI's. (I think it's inconceivable that Goodlatte's version of SAFE could
get to the floor anytime soon.) Whether this happens or not will depend on
the Rules committee, the leadership -- and, most of all, behind-the-scenes
maneuvering.

The Senate, however, appears to be taking much, much longer. But I think
that the national security/l.e. forces can move long before the end of
next summer.

-Declan

{% endraw %}
```

## Thread

+ Return to [September 1997](/archive/1997/09)

+ Return to "[? the Lunatic <hehehe@dev.null>](/authors/_the_lunatic_hehehe_at_dev_null_)"
+ Return to "[Declan McCullagh <declan@pathfinder.com>](/authors/declan_mccullagh_declan_at_pathfinder_com_)"
+ Return to "[Declan McCullagh <declan@well.com>](/authors/declan_mccullagh_declan_at_well_com_)"
+ Return to<EMAIL_ADDRESS>(Ian Goldberg)](/authors/iang_at_cs_berkeley_edu_ian_goldberg_)"
+ Return to "["John Smith" <jsmith58@hotmail.com>](/authors/john_smith_jsmith58_at_hotmail_com_)"
+ Return to "[Lee Tien <tien@well.com>](/authors/lee_tien_tien_at_well_com_)"
+ Return to "[Lucky Green <shamrock@netcom.com>](/authors/lucky_green_shamrock_at_netcom_com_)"
+ Return to "[Will Rodger <rodger@worldnet.att.net>](/authors/will_rodger_rodger_at_worldnet_att_net_)"

+ 1997-09-12 (Sat, 13 Sep 1997 01:27:28 +0800) - [unSAFE won't pass?](/archive/1997/09/8d76bdbb0263060dfb5817c7168275a471f1b5deea69d3d197524345305b39a1) - _"John Smith"<EMAIL_ADDRESS>  + 1997-09-12 (Sat, 13 Sep 1997 04:22:12 +0800) - [Re: unSAFE won't pass?](/archive/1997/09/d738e94d288593440d08d82c438416af386696dd1d6e7d36931b511d765a16e9) - _Lee Tien<EMAIL_ADDRESS>    + 1997-09-12 (Sat, 13 Sep 1997 07:32:47 +0800) - [Note to Net-lobbyists: give it up already, abandon Congress](/archive/1997/09/0d0064352cc31426693fdf60a49c9662801ebc53b7e3ca28411c7e5c5df24818) - _Declan McCullagh<EMAIL_ADDRESS>    + 1997-09-13 (Sat, 13 Sep 1997 10:19:04 +0800) - [Re: Note to Net-lobbyists: give it up already, abandon Congress](/archive/1997/09/8444ac92eb78a056d259bb4bdaf427b3b202e21e224bf99afca6283cbdb4fe58) - _Lucky Green<EMAIL_ADDRESS>      + 1997-09-13 (Sat, 13 Sep 1997 10:31:27 +0800) - [Re: Note to Net-lobbyists: give it up already, abandon Congress](/archive/1997/09/56e2e6faaf311b9cba825ce1b5f1401b1a97eeba72cb17ebf9c259bf168091bb) - _Declan McCullagh<EMAIL_ADDRESS>        + 1997-09-13 (Sat, 13 Sep 1997 11:33:08 +0800) - [The "I Told You So" Website](/archive/1997/09/be8096b6f9451fd3c0ba68108623fc29eac6668081805f29da9bcd6d6c616466) - _? the Lunatic<EMAIL_ADDRESS>    + 1997-09-14 (Mon, 15 Sep 1997 00:41:34 +0800) - [Re: Note to Net-lobbyists: give it up already, abandon Congress](/archive/1997/09/79b8b0a6889acafb0e8f0eaeaab94d038c53db7dcda990ae23ebfd8f36db72c1) -<EMAIL_ADDRESS>(Ian Goldberg)_
  + 1997-09-12 (Sat, 13 Sep 1997 05:18:51 +0800) - [Re: unSAFE won't pass?](/archive/1997/09/7a41edb236ad945d1e39c1ed40c80a0c034280c589e64e45dc0ca3705fe5bece) - _Declan McCullagh<EMAIL_ADDRESS>  + 1997-09-14 (Sun, 14 Sep 1997 23:40:43 +0800) - [Re: unSAFE won't pass?](/archive/1997/09/e73d4dae1dddf51c8826b2c2041a434bfdcdfd259cb743fab3c3304f5fbb4dbc) - _Will Rodger<EMAIL_ADDRESS>    + 1997-09-14 (Mon, 15 Sep 1997 03:55:20 +0800) - Re: unSAFE won't pass? - _Declan McCullagh<EMAIL_ADDRESS>    + 1997-09-15 (Mon, 15 Sep 1997 10:35:08 +0800) - [Re: unSAFE won't pass?](/archive/1997/09/2b0a6aecc83fa062ce41d671ab8343e04145bf827f20d317de2916585382fde6) - _Will Rodger<EMAIL_ADDRESS>


text:
Constituent-parser-nl
=======

Introduction
------------

This is a parser for Dutch text using the Alpino parser (http://www.let.rug.nl/vannoord/alp/Alpino/). The input for this module has to be a valid
KAF file with at least the text layer. The output will be the constituent trees in pennTreebank format for each of the sentences in the input KAF.
The tokenization and sentence splitting is taken from the input KAF file, so if your input file has a wrong tokenization/splitting, the output could
contain errors. The number of output constituent trees will be exactly the same as the number of sentences in your input KAF

Requirements
-----------
* VUKafParserPy: parser in python for KAF files (https://github.com/opener-project/VU-kaf-parser)
* lxml: library for processing xml in python
* Alpino parser:http://www.let.rug.nl/vannoord/alp/Alpino/

Installation
-----------
Clone the repository to your local machine and set the varible ALPINO_HOME in the file core/alpino_parser.py
to point to your local folder of the Alpino parser.

How to run the module with Python
---------------------------------

You can run this module from the command line using Python. The main script is core/alpino_parser.py. This script reads the KAF from the standard input
and writes the output to the standard output, generating some log information in the standard error output. To process one file just run:
````shell
cat input.kaf | core/alpino_parser.py > input.tree
````

This will read the KAF file in "input.kaf" and will store the constituent trees in "input.tree"

Contact
------
* Ruben Izquierdo
* Vrije University of Amsterdam
* ruben.izquierdobevia@vu.nl

repository: opener-project/constituent-parser-nl

repo_name: opener-project/constituent-parser-nl


text:
Obfuscemail
===========

[![Build Status](https://travis-ci.org/mhemmings/obfuscemail.svg?branch=master)](https://travis-ci.org/mhemmings/obfuscemail)
[![Dependency Status](https://david-dm.org/mhemmings/obfuscemail.svg)](https://david-dm.org/mhemmings/obfuscemail)

Adding contact email to your site is a great idea to allow people to contact
you easily. However, it's also a great way to put your email address on a dish
for spammy web crawlers.

Obfuscemail is a simple command line utility and Node.js module to help with
this issue. It generates javascript which creates nice `<a href="mailto:">`
links which appear and work as normal in a web browser, but are not readable by
web crawlers. The actual email address is hidden by the rot13 cipher.

## Installation

To install the command line utility globally:

    sudo npm install -g obfuscemail

Or to install locally in an npm project:

    npm install obfuscemail --save

## Usage

To use in a HTML page, you must define where you want your mailto links to be
injected by using the `obfuscemail` class (ANY element with this class will be
turned into a mailto link).

Then to generate the javascript to include in this page you need to run:

    obfuscemail -e "<your email>" -t "Anchor Tag Text"

You can also add an optional subject to the mailto link:

    obfuscemail -e "<your email>" -t "Anchor Tag Text" -s "Subject for Email"

Obfuscemail can also be used as a Node.js module (see above for installation):

    var obfuscemail = require('obfuscemail');

	var js =<EMAIL_ADDRESS>'Contact Me');

  	console.log(js);
  	/* This outputs an immediately-invoked function expression, which you
  	 * *could*, if you really wish, eval()...
  	 */

## Example

1. Add `<span class="obfuscemail">No email here!</span>` to a HTML page.
2. Generate the javascript `<script>` tag with `obfuscemail -e<EMAIL_ADDRESS>-t "Contact Me!"`. Cut and paste it into your HTML.
3. When the browser loads the page, the span element will be replaced with
`<a<EMAIL_ADDRESS>Me!</a>`

## FAQs

1. **Why use the rot13 cipher?**
It adds the main layer of obfuscation. Bots with an email matching regex over
the whole page will be fooled by this.
2. **But if enough people use rot13, bots will be be written to use it too.**
Yeah, they will. We'll cross that bridge when we get to it.
3. **Eurgh, Node.js command line utilities are horrible!**
Yeah, they are. But so's your face.

repository: mhemmings/obfuscemail

repo_name: mhemmings/obfuscemail


text:
---
alias: meemaesh3k
description: Learn how to deploy your Prisma database service to a local cluster.
---

# Local Prisma server with Docker

If you want to develop without internet access or simply prefer having everything locally, you can use Docker to run Prisma locally.

### Installing Docker

You need an up-to-date version of Docker to run Prisma locally. You can find installation instructions for the free Docker Community Edition (CE) on https://www.docker.com/community-edition

### Set up local Prisma server

Use the interactive `init` command to bootstrap configuration for your Prisma server:

```sh
prisma init
```

Choose `Create new database` and pick MySQL or Postgres.

This will create a `docker-compose.yml` file with a configuration appropriate for running Prisma locally.
Now run `docker-compose up -d` to start Prisma and and empty database of your selected type.

This will download the open source Docker images for Prisma as well as your selected database. It can take a while, depending on your internet connection.

Now you can deploy a service to the local cluster:

```
❯ prisma deploy

? Please choose the cluster you want to deploy "demo@dev" to (Use arrow keys)

  Deploying service `default` to stage `default` to server `local` 169ms
```

### Upgrading local cluster

New versions of Prisma are released every other week. To upgrade, you should first upgrade your CLI:

```sh
npm -g install prisma
```

You can now update your Prisma server by manually changing the `docker-compose.yml` file to use the latest version of Prisma:

Before:

```yml
version: '3'
services:
  prisma:
    image: prismagraphql/prisma:1.13
```

After:

```yml
version: '3'
services:
  prisma:
    image: prismagraphql/prisma:1.14
```

For the change to take effect, run:

```sh
docker-compose up -d
```

> Note: It is recommended to export your data before upgrading, using the `prisma export` command.

If you run into issues during or after upgrading, you can use normal docker commands to remove your docker containers and start from scratch:

- `docker ps` to list your containers
- `docker stop [CONTAINER ID]` to stop a container
- `docker rm [CONTAINER ID]` to remove the container

### Access your database directly

To learn how you can access your MySQL database directly, follow [this](!alias-eechaeth3l) tutorial.

repository: mxstbr/prisma

repo_name: mxstbr/prisma


text:
# Partykals

Particles system library for THREE.js with a really lame name!

Live demo can be found [here](https://ronenness.github.io/partykals/demo/index.html).
![Demo Screenshot](demo/screenshot.png)

## Why

THREE.js provides just the basics to create particles system, but it requires a lot of work to actually have working particles. This is what this library is for.

There are many alternatives and more robust particle systems for THREE.js out there, but at the time of writing these lines (15/12/2019) none of the ones I found works with latest THREE version (r111).

# Setup

To start using Partykals either include script `dist/partykals.js` in your HTML pages, or import via NPM:

`npm install partykals`

`Partykals` will try to find THREE.js either in global space (under `window` object) or by using require('three'). One of these options must be available in order for it to work.

# Usage

To create a new particles system:

```js
var system = new Partykals.ParticlesSystem({
        container: scene, // <-- THREE.JS object to attach system to.
        particles: {
            // particles options, will be described later..
        },
        system: {
            // system options, will be described later..
            emitters: // emitter(s), will be described later
        }
    });
```

And then to update system, you need to call `update()` every frame:

```js
system.update();
```

## Quick Example

Now lets take a look at a short working example:

```js
// scene and renderer are assumed to be created here..

// create  particles system:
var system = new Partykals.ParticlesSystem({
    container: scene,
    particles: {
        globalSize: 5,
        ttl: 10,
        velocity: new Partykals.Randomizers.SphereRandomizer(12.5),
        velocityBonus: new THREE.Vector3(0, 25, 0),
        gravity: -10,
        startColor: new Partykals.Randomizers.ColorsRandomizer(),
        endColor: new Partykals.Randomizers.ColorsRandomizer(),
    },
    system: {
        particlesCount: 1000,
        emitters: new Partykals.Emitter({
            onInterval: new Partykals.Randomizers.MinMaxRandomizer(0, 5),
            interval: new Partykals.Randomizers.MinMaxRandomizer(0, 0.25),
        }),
        speed: 1,
    }
});

// update loop
function animate() {

    requestAnimationFrame( animate );
    system.update();
    renderer.render( scene, camera );

}
```

For more info, check out the demo in the `demo/` folder.

## Particles Options

Particles options are all the settings related to the particles themselves.
Options are (pasted from code):

```js
/*
* // PARTICLES OPTIONS
* ============================================================================
* @param {*} options.particles Particle-related options.
*
* // PARTICLES TTL
* @param {Number} options.particles.ttl How long, in seconds, every particle lives.
* @param {Number} options.particles.ttlExtra If provided, will add random numbers from 0 to ttlExtra to particle's ttl.
*
* // PARTICLES FADING / ALPHA
* @param {Boolean} options.particles.alpha Per-particle constant alpha; either a constant value (Number) or a Partykals.Randomizers.Randomizer instance to create random values.
* @param {Number} options.particles.startAlpha Particles starting opacity; either a constant value (Number) or a Partykals.Randomizers.Randomizer instance to create random values.
* @param {Number} options.particles.endAlpha Particles ending opacity; either a constant value (Number) or a Partykals.Randomizers.Randomizer instance to create random values.
* @param {Number} options.particles.startAlphaChangeAt Will only start shifting alpha when age is over this value; either a constant value (Number) or a Partykals.Randomizers.Randomizer instance to create random values.
*
* // PARTICLES GROWING / SIZE
* @param {Number} options.particles.size Per-particle constant size; either a constant value (Number) or a Partykals.Randomizers.Randomizer instance to create random values.
* @param {Number} options.particles.startSize Particles starting size; either a constant value (Number) or a Partykals.Randomizers.Randomizer instance to create random values.
* @param {Number} options.particles.endSize Particles ending size; either a constant value (Number) or a Partykals.Randomizers.Randomizer instance to create random values.
* @param {Number} options.particles.startSizeChangeAt Will only start shifting size when age is over this value; either a constant value (Number) or a Partykals.Randomizers.Randomizer instance to create random values.
*
* // PARTICLES COLORING
* @param {THREE.Color} options.particles.color Per-particle constant color; either a constant value (THREE.Color) or a Partykals.Randomizers.Randomizer instance to create random values.
* @param {THREE.Color} options.particles.startColor Starting color min value; either a constant value (THREE.Color) or a Partykals.Randomizers.Randomizer instance to create random values.
* @param {THREE.Color} options.particles.endColor Ending color min value; either a constant value (THREE.Color) or a Partykals.Randomizers.Randomizer instance to create random values.
* @param {Number} options.particles.startColorChangeAt Will only start shifting color when age is over this value; either a constant value (Number) or a Partykals.Randomizers.Randomizer instance to create random values.
*
* // PARTICLES ACCELERATION
* @param {THREE.Vector3} options.particles.acceleration Particles acceleration; either a constant value (THREE.Vector3) or a Partykals.Randomizers.Randomizer instance to create random values.
* @param {Number} options.particles.gravity Gravity force affecting the particles.
*
* // PARTICLES ROTATION
* @param {Number} options.particles.rotation Per-particle rotation (only works with texture); either a constant value (Number) or a Partykals.Randomizers.Randomizer instance to create random values.
* @param {Number} options.particles.rotationSpeed Particles rotation speed (only works with texture); either a constant value (Number) or a Partykals.Randomizers.Randomizer instance to create random values.
*
* // PARTICLES VELOCITY
* @param {*} options.particles.velocity Particles starting velocity; either a constant value (THREE.Vector3) or a Partykals.Randomizers.Randomizer instance to create random values.
* @param {THREE.Vector3} options.particles.velocityBonus Velocity value to add to all particles after randomizing velocity.
*
* // PARTICLES OFFSET
* @param {THREE.Vector3} options.particles.offset Particles offset from system's center; either a constant value (THREE.Vector3) or a Partykals.Randomizers.Randomizer instance to create random values.
*
* // PARTICLE GLOBALS
* @param {Boolean} options.particles.worldPosition If true, particles will maintain their world position after spawn even if the system moves.
* @param {Number} options.particles.globalSize Const size for all particles. Note: this is more efficient than setting per-particle size property.
* @param {Number} options.particles.globalColor Global color to affect all particles. Note: this is more efficient than setting per-particle color property.
* @param {String} options.particles.blending Particles blending mode (opaque / blend / additive).
* @param {THREE.Texture} options.particles.texture Particle's texture to use.
*
* // CUSTOM CALLBACKS
* @param {Function} options.particles.onUpdate Optional method to call per-particle every update frame.
* @param {Function} options.particles.onSpawn Optional method to call per-particle every time a particle spawns (after everything is set).
*  */
```

## System Options

The system options are options related to the system itself or the material used.
Options are (pasted from code):

```js
/*
* // SYSTEM OPTIONS
* ============================================================================
* @param {*} options.system System-related options.
* @param {Number} options.system.particlesCount Particles count.
* @param {Number} options.system.ttl How long, in seconds, the particle system lives.
* @param {Number} options.system.speed Speed factor to affect all particles and emitting. Note: the only thing this don't affect is system's ttl.
* @param {Function} options.system.onUpdate Optional method to call every update frame.
* @param {Partykals.Emitter} options.system.emitters A single emitter or a list of emitters to attach to this system.
* @param {Boolean} options.system.perspective If true, will scale particles based on distance from camera.
* @param {Number} options.system.scale Overall system scale when in perspective mode (if perspective=false, will be ignored).  As you can see above, when creating the particles system you need to provide an emitter (or list of emitters). You can also attach emitters after creation with `system.addEmitter(emitter)`.

To create a new emitter:

```js
var emitter = new Partykals.Emitter(options);
```

Emitter options are (paste from code):

```js
/*
* @param {*} options Emitter options.
* @param {*} options.onSpawnBurst Burst of particles when particle system starts; either a constant value (Number) or a Partykals.Randomizers.Randomizer instance to create random numbers.
* @param {*} options.onInterval Burst of particles every interval; either a constant value (Number) or a Partykals.Randomizers.Randomizer instance to create random numbers.
* @param {Number} options.interval Spawn interval time, in seconds; either a constant value (Number) or a Partykals.Randomizers.Randomizer instance to create random numbers.
* @param {Number} options.detoretingMinTtl If provided and particle system's ttl is below this value, will start emitting less and less until stopping completely.
*/
```

## Randomizers

Randomizers are classes that generate random numbers, vectors, colors and more. We use them, as guessed, to generate randomness in our particles system (most particles-level options can either be a constant value, or a randomizer, to get random per-particle value).

For more info, check out the randomizers under `randomizers/` folder, or under `Partykals.Randomizers` namespace.

## Changes

### 1.0.1

- Added bower package.
- Added npm package.
- Added dispose method.
- Changed the logic of 'finished' flag - will now consider systems finished when ttl expired and there are no particles left.
- Added some useful API functions and getters, like getting particles count or remove & dispose if done.
- Added startAlphaChangeAt, startSizeChangeAt, and startColorChangeAt to only start transitions after some time passes.
- Some minor bugfixes

### 1.0.2 [WIP]

- Fixed `dispose` to also dispose the material.

## License

`Partykals` is released under the permissive MIT license and is absolutely free for any (legal) purpose, commerical included.


text:
---
title: Flutter Info Bundle
layout: post
date: 2020-06-07 18:11:09
categories: Flutter Mobile
---

## Libs
- [Provider](https://github.com/rrousselGit/provider)
- [Bloc implementation](https://felangel.github.io/bloc/)

## Youtube
- [Pragmatic State Management in Flutter (Google I/O'19)](https://www.youtube.com/watch?v=d_m5csmrf7I&t=226s)

## Reading

- [Bloc](https://medium.com/flutterpub/architecting-your-flutter-project-bd04e144a8f1)
- [Why use RxDart and how we can use with BLoC Pattern in Flutter?](https://medium.com/flutter-community/why-use-rxdart-and-how-we-can-use-with-bloc-pattern-in-flutter-a64ca2c7c52d)
- [Flutter BLoC Pattern for Dummies Like Me](https://medium.com/flutter-community/flutter-bloc-pattern-for-dummies-like-me-c22d40f05a56)
- [Coreconcepts/Lib by felangel](https://felangel.github.io/bloc/#/coreconcepts)
- [Architect your Flutter project using BLOC pattern](https://medium.com/flutterpub/architecting-your-flutter-project-bd04e144a8f1)
- [Effective bloc pattern](https://medium.com/flutterpub/effective-bloc-pattern-45c36d76d5fe)
- [Reactive Programming - Streams - BLoC](https://www.didierboelens.com/2018/08/reactive-programming---streams---bloc/)
- [Reactive Programming - Streams - BLoC - Practical Use Cases](https://www.didierboelens.com/2018/12/reactive-programming---streams---bloc---practical-use-cases/)


text:
GetText.NET
========

A cross-platform .NET implementation of the GNU Gettext library, initially forked from [NGettext](https://github.com/VitaliiTsilnyk/NGettext).
GetText.NET supports [**string interpolation**](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/tokens/interpolated) and [**FormattableString**](https://docs.microsoft.com/en-us/dotnet/api/system.formattablestring?redirectedfrom=MSDN&view=netcore-3.1).
GetText.NET.Extractor extracts string values from C# source code in  GetText.ICatalog method calls to Get\*String(), and also supports localizing Windows.Forms.Control properties showing text, such as .Text, .HeaderText or .ToopTipText.

GetText.NET has simplified usage over NGetText and original GNU Gettext tools, i.e. removed Get\*String**Fmt**() methods and pass parameters directly to Get\*String() overloads, and also removed the need for LC_MESSAGES subfolder to place translation files.

This fully managed library targets **Microsoft .NET Standard 2.0** to support a wide range of .NET implementations including **.NET Framework** >=4.6.1, **.NET Core** >=2.0, **Mono** and [more](https://github.com/dotnet/standard/blob/master/docs/versions/netstandard2.0.md).
It is fully **COM** and **CLS** compatible.

Translations are loaded directly from gettext *.mo files. Multiple translation domains and multiple locales can be loaded in one application instance. There is no need to compile satellite assemblies. GetText.NET supports both little-endian and big-endian MO files, automatic (header-based) encoding detection and (optional) plural form rules parsing.

Documentation and Samples
---------------
For details on each product, examples and FAQ please check the [Wiki](https://github.com/perpetualKid/GetText.NET/wiki) pages.

Version History
---------------

Please check [Releases Notes](ReleaseNotes.md) for version history

Status
---------------

[![Build Status](https://dev.azure.com/perpetualKid/GetText.NET/_apis/build/status/Azure%20Cloud%20Build?branchName=v0.12)](https://dev.azure.com/perpetualKid/GetText.NET/_build/latest?definitionId=18&branchName=v0.12)

| Package | Status |
| ----------- | ----------- |
|GetText.NET|[![Nuget (with prereleases)](https://img.shields.io/nuget/vpre/gettext.net?color=brightgreen&style=plastic)](https://www.nuget.org/packages/gettext.net)|
|GetText.NET.PluralCompile|[![Nuget (with prereleases)](https://img.shields.io/nuget/vpre/gettext.net.pluralcompile?color=brightgreen&style=plastic)](https://www.nuget.org/packages/GetText.NET.PluralCompile/)|
|GetText.NET.WindowsForms|[![Nuget (with prereleases)](https://img.shields.io/nuget/vpre/GetText.NET.WindowsForms?color=brightgreen&style=plastic)](https://www.nuget.org/packages/GetText.NET.WindowsForms/)|
|GetText.NET.Extractor|[![Nuget (with prereleases)](https://img.shields.io/nuget/vpre/gettext.net.extractor?color=brightgreen&style=plastic)](https://www.nuget.org/packages/GetText.NET.Extractor/)|

For further details on each product, also check the [Wiki](https://github.com/perpetualKid/GetText.NET/wiki) pages.


text:
# WaniKani More Hotkeys

Adds hotkeys for “wrap up” (**Shift+W**), “add synonym” (**S**), “edit meaning note” (**M**), “edit reading note” (**R**)…

See [here](https://community.wanikani.com/t/userscript-wanikani-more-hotkeys/39979) for documentation.

## Installation

[Install Tampermonkey](https://community.wanikani.com/t/visual-guide-on-how-to-install-a-userscript/12136), then click [here](https://github.com/lynn/wanikani-more-hotkeys/raw/master/hotkeys.user.js).

repository: lynn/wanikani-more-hotkeys

repo_name: lynn/wanikani-more-hotkeys


text:
# Easily benchmark you're requests

[![Latest Version on Packagist](https://img.shields.io/packagist/v/mtolhuys/laravel-request-benchmark.svg?style=flat-square)](https://packagist.org/packages/mtolhuys/laravel-request-benchmark)
[![Build Status](https://img.shields.io/travis/mtolhuys/laravel-request-benchmark/master.svg?style=flat-square)](https://travis-ci.org/mtolhuys/laravel-request-benchmark)
[![Quality Score](https://img.shields.io/scrutinizer/g/mtolhuys/laravel-request-benchmark.svg?style=flat-square)](https://scrutinizer-ci.com/g/mtolhuys/laravel-request-benchmark)
[![Total Downloads](https://img.shields.io/packagist/dt/mtolhuys/laravel-request-benchmark.svg?style=flat-square)](https://packagist.org/packages/mtolhuys/laravel-request-benchmark)

This package comes with a benchmark middleware which, if included, will measure your requests time and memory usage.

## Installation

You can install the package via composer:

```bash
composer require mtolhuys/laravel-request-benchmark
```

## Usage

Add the `'benchmark'` middleware to the routes you want to measure f.e.:
``` php
Route::group(['middleware' => ['foo', 'bar', 'benchmark']], function() {
    // benchmarked routes
});

// Or

Route::get('/', 'IndexController@index')->middleware('benchmark');
```
Out of the box this will create debug log entries f.e.:
```text
[yyyy-mm-dd hh:mm:ss] local.DEBUG: request-benchmark: GET[http://localhost]
Time: 1.05ms
Pre memory usage 3169Kb
Post memory usage 3296Kb (127Kb)
```
As well as a overview page on route `/request-benchmark` containing a table showing the results stored in `request-benchmark.json` file.

This behavior is configurable with the included request-benchmark config file.
Run `php artisan vendor:publish --provider="Mtolhuys\LaravelRequestBenchmark\LaravelRequestBenchmarkServiceProvider"` if you don't see it in your config/ folder.
```php
return [
    'enabled' => true, // set to false to globally stop benchmark
    'log' => true, // set to false to stop creating log entries
    'storage_path' => null, // if specified it will create a request-benchmark.json containing all data
];
```

### Testing

``` bash
composer test
```

### Changelog

Please see [CHANGELOG](CHANGELOG.md) for more information what has changed recently.

## Contributing

Please see [CONTRIBUTING](CONTRIBUTING.md) for details.

### Security

If you discover any security related issues, please email<EMAIL_ADDRESS>instead of using the issue tracker.

## Credits

- [Maarten Tolhuijs](https://github.com/mtolhuys)
- [All Contributors](../../contributors)
- [Laravel Package Boilerplate](https://laravelpackageboilerplate.com)

## License

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

repository: mtolhuys/laravel-request-benchmark

repo_name: mtolhuys/laravel-request-benchmark


text:
---
title: Fish shell
emoji: 🐠
tags:
  - cli
link: https://fishshell.com
date: 2021-11-26
---

My Fish config: https://github.com/mrmartineau/fish

Change fish settings:

```shell
fish_config
```

Reload fish shell

```shell
fish
```

## Switching to fish?

If you wish to use fish (or any other shell) as your default shell, you need to enter your new shell's executable in two places.

Add the shell to `/etc/shells` with:

```sh
echo /usr/local/bin/fish | sudo tee -a /etc/shells
```

> ℹ homebrew may install fish to `/opt/homebrew/bin/fish`

Change your default shell with:

```sh
chsh -s /usr/local/bin/fish
```

> This assumes you installed fish to `/usr/local/bin`, which is the default location when you've compiled it yourself. If you installed it with a package manager, the usual location is `/usr/bin/fish`, but package managers typically already add it to `/etc/shells`. Just substitute the correct location.

(To change it back to another shell, substitute `/usr/local/bin/fish` with `/bin/bash`, `/bin/tcsh` or `/bin/zsh` as appropriate in the steps above.)

http://fishshell.com/docs/current/tutorial.html
https://github.com/jorgebucaran/fish-cookbook
https://github.com/ghaiklor/iterm-fish-fisher-osx

## Fish features

### Functions

Create new functions in `~/.config/fish/functions` e.g. `xyz.fish`

### Aliases

`alias` is a simple wrapper for the `function` builtin, which creates a function wrapping a command.

https://fishshell.com/docs/current/cmds/alias.html

```sh
alias gco 'git checkout'
alias undocommit 'git reset HEAD~1'
alias ya 'yarn add'
alias yad 'yarn add -D'
```

### abbr

If you add an [abbreviation](https://fishshell.com/docs/current/cmds/abbr.html) instead of an alias you'll get better auto-complete. In fish abbr more closely matches the behavior of a bash alias.

```sh
abbr -a gco git checkout
```

Will add a new abbreviation `gco` that expands to `git checkout`.

## Fish plugins

### Fisher

https://github.com/jorgebucaran/fisher

Plugins are listed in the `$__fish_config_dir/fish_plugins` file.

Install fisher:

```sh
curl -sL https://git.io/fisher | source && fisher install jorgebucaran/fisher
```

Install a plugin:

```sh
fisher install<EMAIL_ADDRESS>```

Listing plugins

```sh
fisher list
```

## Other info

### Set shell variables

```sh
set -xg PATH /usr/local/sbin $PATH
```

https://fishshell.com/docs/current/cmds/set.html

#### Adding to `$PATH`

Use [`fish_add_path`](https://fishshell.com/docs/current/cmds/fish_add_path.html)

```sh
fish_add_path /usr/local/sbin
```

https://fishshell.com/docs/current/cmds/fish_add_path.html

#### List all $PATH entries

```sh
string join \n $PATH | nl
```

### Using `ssh-agent`

When needing to add ssh keys to Github, [the docs](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent#adding-your-ssh-key-to-the-ssh-agent) suggest running `eval "$(ssh-agent -s)"` but that does not work in fish. Run this instead:

```sh
command ssh-agent -s
```

### Executing Bash

If fish is your default shell and you want to copy commands from the internet that are written in bash (the default shell on most systems), you can proceed in one of the following two ways:

Use the bash command with the -c switch to read from a string:

```sh
$ bash -c 'some bash command'
```

Use bash without a switch to open a bash shell you can use and exit afterward:

```sh
> bash
$ some bash command
$ exit

> _
```

gha_language: TypeScript


text:
# Changelog

## v2.0.0

- Refactor testing environment. Now using Hardhat, Ethers and Waffle. This should give players a better debugging experience, and allow them to familiarize with up-to-date JavaScript tooling for smart contract testing.
- New levels:
    - Backdoor
    - Climber
    - Free Rider
    - Puppet v2
- New integrations with Gnosis Safe wallets, Uniswap v2, WETH9 and the upgradebale version of OpenZeppelin Contracts.
- Tweaks in existing challenges after community feedback
    - Upgraded most contracts to Solidity 0.8
    - Changes in internal libraries around low-level calls and transfers of ETH. Now mostly using OpenZeppelin Contracts utilities.
    - In existing Puppet and The Rewarder challenges, better encapsulate issues to avoid repetitions.
    - Reorganization of some files
- Changed from `npm` to `yarn` as dependency manager

## v1.0.0

Initial version

repository: werew/CTFs

gha_language: C

repo_name: werew/CTFs


text:
# Elixir Films

## Running it
### Requirements
You'll have to get installed in your machine the following softwares versions for better testing experience:
- Elixir 1.10.2 (compiled with Erlang/OTP 22)
- Postgres 9.6
### Commands
Elixir code setup:
```
$ git clone git@github.com:abmBispo/elixir-films.git
$ cd elixir-films
$ mix deps.get
```

Postgres database (running in docker):
```
docker run --name postgres-database -e POSTGRES_PASSWORD=postgres -d -p 5432:5432 -v $HOME/docker/volumes/postgres:/var/lib/postgresql/data postgres
```

In order to run it with no docker, you'll also have to modify the `config/dev.exs` file, configuring it to access local (`<IP_ADDRESS>`) database:
```ex
config :elixir_films, ElixirFilms.Repo,
  username: "postgres",
  password: "postgres",
  database: "elixir_films_dev",
  hostname: "<IP_ADDRESS>",
  pool: 10
```

Now migrate the models with:
```
$ mix ecto.migrate
```

And have fun:
```
$ mix phx.server
```

### Alternative: `docker-compose`
Or you can alternatively get it all via `docker-compose` just by installing it (my version was **1.21.2, build a133471**) and enter:
```
$ docker-compose build
$ docker-compose run web mix ecto.create
$ docker-compose run web mix ecto.migrate
$ docker-compose up
```

## Testing

Want to test it? [Postman lib here](https://documenter.getpostman.com/view/479599/TVRrWQiU).

repository: abmBispo/elixir-films

repo_name: abmBispo/elixir-films


text:
# Dacryomitra lutea (Massee) Lloyd, 1921 SPECIES

#### Status
SYNONYM

#### According to
The Catalogue of Life, 3rd January 2011

#### Published in
Mycol. Writ. 6: 1048 (1921)

#### Original name
null

### Remarks
null

repository: mdoering/backbone

path: /life/Fungi/Basidiomycota/Dacrymycetes/Dacrymycetales/Dacrymycetaceae/Calocera/Calocera lutea/ Syn. Dacryomitra lutea/README.md

repo_name: mdoering/backbone


text:
---
layout: post
title: Bukito - Assembled
date: '2014-09-23T00:46:00.001-07:00'
author: Dave Hylands
tags:
- 3D-Printing
- Bukito
modified_time: '2014-09-23T15:42:40.329-07:00'
thumbnail: http://4.bp.blogspot.com/-RgT4sKQhS9o/VCEkHmGnOmI/AAAAAAAAYn4/ZT5lJRzwrLM/s72-c/Assembled.jpg
blogger_id: tag:blogger.com,1999:blog-2189571833278528716.post-2512763966043716747
blogger_orig_url: http://blog.davehylands.com/2014/09/bukito-assembled.html
---

My [Bukito 3D Printer](https://www.kickstarter.com/projects/deezmaker/bukito-portable-3d-printer-take-it-everywhere)
showed up in the mail today. This was also a KickStarter. It's only about 9 months late, but it looks like it was
worth the wait.

[![]({{ site.url }}/images/2014-09-23/image-0000.jpg)]({{ site.url}}/images/2014-09-23/image-0000.jpg)

It came as a kit, and took about 3 hours to put together. Now to level the
table and do a first print (maybe tomorrow - time to go to bed now).

The build volume is about 5" x 6" x 6" which should be fine for most of the
stuff I want to do. I figured I'd start small and then once I'm comfortable
with a 3D printer, and know what I like and dislike, I can invest in a bigger
printer.

I just discovered [Nick Lievendag's blog](http://nicklievendag.com/) and it
will be interesting to see how his evaluations turn out (for consideration in
buying a larger printer).

gha_language: SCSS


text:
# WSU_PHYS6850_W21_repo

[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/chunshen1987/WSU_PHYS6850_W21_repo/HEAD)

This is a public code repository for the course PHYS6850 Winter 2021 at Wayne State.
This repository includes demos and exercises jupyter notebooks for the course.