n1 is the number of categories of field 1.
n2 is the number of categories of field 2.
Display various quantities computed from the contingency table of the two fields :
- The phi coefficient (if n1=2 and n2=2)
- The tetrachoric correlation (approximed)
- The C coefficient
- The Cramér's V coefficient
- The mutual mutual information
- The uncertainty coefficient
- The Goodman and Kruskal's lambda coefficient
In the top slot, the first field.
In the left slot, the second field.


-
SIMPLE
A very simple Wookmark setup. -
AMD
Dynamically loading Wookmark via AMD. -
Remote API
Displaying images from a remote API. -
PHP server
Displaying images from a custom php server. -
Endless scroll
Automatically load new content when scrolling down. -
Filtering
Showing and hiding tiles based on user-controlled filters. -
Flexible width
Automatically adjusting tiles to always fill the container width. -
Lightbox
Showing a lightbox when users click tiles. -
Load it all
Load the plugin after all images have loaded. -
Placeholders
Displaying placeholders at the bottom to create even-sized columns. -
Sorting
Let users change the sort order of your tiles. -
Stamping
Stamping tiles to specific positions in the layout.


Make Show Ads Asynchronous
Note: New feature as of <IP_ADDRESS>.
Configuration
The 'Make Show Ads Asynchronous' filter is enabled by specifying:
- Apache:
ModPagespeedEnableFilters make_show_ads_async
- Nginx:
pagespeed EnableFilters make_show_ads_async;
Description
The filter rewrites pages that load
Google AdSense ads with the
synchronous show_ads.js
snippet to load them with the
asynchronous adsbygoogle.js
instead.
Loading AdSense asynchronously
helps keep ads
from delaying
the rest of the page content.
Operation
The filter looks for a Google AdSense snippet such as the following:

and rewrites such snippets in-place to:

Example
You can see the filter in action at www.modpagespeed.com
on this
example.
Requirements
This filter requires that ads specify a specific width and height
with google_ad_width
and google_ad_height
.
If google_ad_output
is specified it must be set
to html
. Alternate outputs like js
or json_html
are not supported by adsbygoogle.js
.
Ad snippets that don't meet these requirements won't be rewritten. Other ad
blocks on the same page will still be rewritten, loading
both show_ads.js
and adsbygoogle.js
. To avoid this,
we recommend not enabling this filter for pages that have a mixture of
eligible and ineligible ad blocks.
Risks
This filter is considered high risk.
The make_show_ads_async
filter is experimental and has not had
extensive real-world testing. It manipulates JavaScript, which is always
risky, and if errors keep ads from displaying that could mean lost revenue for
your site.


{% include 'header.html' %}
{% include 'menu.html' %}
{% include 'project/sidebar.html' %}
Add/Edit hosts
Column numbers (0 if not):
IPv4 or IPv6:
Hostname:
Description:
Operation System:
Online:
In scope:
Delimiter:
Plaintext file:
Static row fields (every row):
IPv4 or IPv6:
Hostname:
Description:
Operation System:
Threats:
High
Medium
Low
Information
Need to check
Need to recheck
Firewall enabled
Offline
In work...
In scope
Out of scope
Checked
Critical server
Slow connection
or input file content here:
Add
{% if errors is defined and errors %}
There were some errors with hosts
{% for error in errors %}
{{ error }}
{% endfor %}
{% endif %} {% if errors is defined and not errors %}
Hosts were added successfully!
{% endif %}
{% include 'footer.html' %}


---
layout: page
image: CLAMedia.jpg
title: "What are CLAMs?"
subtitle: "A short introduction."
midimage: team.jpg
midtitle:
midsubtitle:
---
CLAMS are a form of digital value, or currency, that is transferred, created, and verified by the collective effort of the computers running the CLAMS software. Similar to Bitcoin, the original technology on top of which CLAMS was created, this network follows a rigorous protocol to ensure that consensus and verification is maintained.
{% include pageMidTitle.html %}
People like yourself run the CLAMs software all over the world, forming one giant decentralized network. To become a part of the CLAMS network, you need only to run the CLAMS software on your home computer. The purpose of this network is to independently and collaboratively verify the transfer and creation of CLAMs. The more people who join the CLAMs network, the stronger it gets.


EUR/USD flirting with daily highs around 1.1080
by Pablo Piovano- EUR/USD returns to the upper end of the range near 1.1080.
- DXY recedes from tops in the vicinity of 97.90.
- US housing data came in on a mixed tone.
After bottoming out in the boundaries of 1.1060, EUR/USD has managed to regain some poise and is now testing daily highs in the 1.1080 area.
EUR/USD looks to USD for direction
The pair has returned to the positive territory on Monday after briefly testing lows in the 1.1060 region. However, a breakout of the current topside in the 1.1080/90 band remains elusive for the time being and is considered crucial in order to visit the 1.1100 neighbourhood and beyond.
On the USD-side, the pullback of the greenback from daily highs comes along another correction lower in US 10-year yields to the 1.80% area against the usual backdrop of US-China developments on the trade front. It is worth mentioning that these yields were hovering around 1.96% during last week.
In the data space and while investors wait for the ECB minutes and the speech by C.Lagarde later in the week, September’s Current Account surplus in Euroland shrunk a tad to €28.2 billion. Across the pond, Housing Starts expanded by 1.314M units (or 3.8%) during last month and Building Permits surpassed estimates expanding by 1.461M units (or 5.0%).
What to look for around EUR
Spot is prolonging the rebound from last week’s lows in sub-1.10 levels, always underpinned by the renewed weakness around the greenback and hopes of a US-China trade deal. The up move, however, seems to have met a tough hurdle in the 1.1080/90 band for the time being. On the macro view, the outlook in Euroland remains fragile and does nothing but justify the ‘looser for longer’ monetary stance by the ECB and the bearish view on the single currency in the medium term at least. In this regard, all the attention will be on the publication of flash PMIs for the current month later in the week.
EUR/USD levels to watch
At the moment, the pair is advancing 0.05% at 1.1077 and faces the next up barrier at 1.1081 (high Nov.19) followed by 1.1091 (100-day SMA) and finally 1.1179 (monthly high Oct.21). On the downside, a breach of 1.0989 (monthly low Nov.14) would target 1.0925 (low Sep.3) en route to 1.0879 (2019 low Oct.1).


|
Biomedical Image Analysis Library
The Biomedical Image Analysis Library is a poweful tool for developers, physicians, researchers, engineers, and so on.
|
Magnetic Resonance Image class. More...
#include <NiftiHeader.hpp>
Public Member Functions | |
| NiftiHeader () | |
| Basic Constructor. More... | |
| NiftiHeader (const Vector< size_t > &new_dim, const Vector< float > &new_pixdim, NiftiType new_datatype=NiftiType::INT8, bool one_file=true) | |
| Basic Constructor. More... | |
| template<class D > | |
| NiftiHeader (const Image< D > &img, bool one_file=true) | |
| Basic Constructor. More... | |
| NiftiHeader (const std::string &filename) | |
| Basic Constructor. More... | |
| const Vector< size_t > & | Dim () const |
| Returns a reference to dimension vector. More... | |
| size_t | Size (size_t dms) const |
| Returns the size of a given image dimension. More... | |
| void | Size (size_t dms, size_t val) |
| Updates image dimension size. More... | |
| const Vector< float > & | PixelSize () const |
| Returns a reference to pixel dimension vector. More... | |
| float | PixelSize (size_t dms) const |
| Returns the pixel size of a given image dimension. More... | |
| void | PixelSize (size_t dms, float val) |
| Updates Pixel dimension size. More... | |
| short | BitPix () const |
| Returns the number of bits per pixel. More... | |
| NiftiType | DataType () const |
| Returns data type code. More... | |
| void | Write (OFile &file, bool one_file) const |
| Writes this nifti header to file. More... | |
| void | Write (const std::string &filename) const |
| Writes this nifti header to file with filename 'filename'. More... | |
| void | DataType (NiftiType type) |
| Changes header information to support data of type 'type'. More... | |
| void | QuaternToMat (const Vector< float > &pixel_dim) |
| Translates quaterns to 4x4 matrix used to convert from xyz to ijk space. More... | |
| void | MatToQuatern () |
| Translates 4x4 matrix used to convert from xyz to ijk space to quaterns. More... | |
| std::string | Orientation (size_t row) const |
| Returned std::string can be: LR, RL, SI, IS, AP, PA, or Undefined. More... | |
| std::string | Orientation () const |
| Returned std::string will be a composition of three values containing: LR, RL, SI, IS, AP, or PA, or Undefined std::string. More... | |
| bool | UseQuatern () |
| Returns a boolean value indicating if this MR image uses quaternion orientation form or not. More... | |
| bool | UseAffine () |
| Returns a boolean value indicating if this MR image uses affine orientation form or not. More... | |
| void | QuaternMatrix (const Matrix< float > mat) |
| Assigns mat data to qtm. More... | |
| Matrix< float > | QuaternMatrix () const |
| returns a copy of qtm. More... | |
| void | QuaternOffset (float x, float y, float z) |
| Sets quatern offset. More... | |
| void | AffineMatrix (const Matrix< float > mat) |
| Assigns mat data to stm. More... | |
| Matrix< float > | AffineMatrix () const |
| returns a copy of stm. More... | |
| template<class O > | |
| O & | PrintOrientation (O &os) const |
| Prints nifti orientation information to output stream 'os'. More... | |
| template<class O > | |
| O & | Print (O &os) const |
| Prints nifti header information to output stream 'os'. More... | |
Static Public Member Functions | |
| static NiftiHeader | Read (const std::string &filename) |
| Returns a nifti header read from file with filename 'filename'. More... | |
| static bool | IsNiftiFile (const std::string &filename) |
| Returns true if given file has nifti extension. More... | |
| static std::string | HeaderFileName (const std::string &filename) |
| Returns nifti header file name associated to filename. More... | |
| static std::string | DataFileName (const std::string &filename) |
| Returns nifti data file name associated to filename. More... | |
| static std::string | ExistingHeaderFileName (const std::string &filename) |
| Returns existing nifti header file name associated to filename. More... | |
| static std::string | ExistingDataFileName (const std::string &filename) |
| Returns existing nifti data file name associated to filename. More... | |
| static size_t | AxialDimension (const std::string &orientation) |
| Returns the number of the image dimension that corresponds to axial direction. More... | |
| static size_t | CoronalDimension (const std::string &orientation) |
| Returns the number of the image dimension that corresponds to coronal direction. More... | |
| static size_t | SagittalDimension (const std::string &orientation) |
| Returns the number of the image dimension that corresponds to sagittal direction. More... | |
| static bool | SuperiorInferior (const std::string &orientation) |
| Returns true if axial dimension direction is superior-inferior. More... | |
| static bool | AnteriorPosterior (const std::string &orientation) |
| Returns true if coronal dimension direction is anterior-posterior. More... | |
| static void | SwapNBytes (size_t n, int siz, void *ar) |
| Swaps bytes of data pointed by ar. Used to read data written by different architectures. More... | |
| static bool | IsSwapped (const std::string filename) |
| Verifies if header nifti file corresponding to filename must swap bytes order. More... | |
| static NiftiType | DataType (const std::string &filename) |
| Returns the type of the data in given file. More... | |
| static void | DataTypeSizes (int datatype, size_t &nbyper, size_t &swapsize) |
| Computes the number of bytes of each element and the bytes to be swapped. More... | |
Static Public Attributes | |
| static const short | NIFTI_HEADER_SIZE = 348 |
| static const short | ANALYZE_EXTENT = 16384 |
Friends | |
| template<class D > | |
| class | Image |
Magnetic Resonance Image class.
Definition at line 248 of file NiftiHeader.hpp.
| Bial::NiftiHeader::NiftiHeader | ( | ) |
Basic Constructor.
| none. |
| Bial::NiftiHeader::NiftiHeader | ( | const Vector< size_t > & | new_dim, |
| const Vector< float > & | new_pixdim, | ||
| NiftiType | new_datatype = NiftiType::INT8 , |
||
| bool | one_file = true |
||
| ) |
Basic Constructor.
| new_dim | Vector with MR image dimensions. |
| new_pixel_dim | array with pixel dimensions. |
| new_datatype | nifti header data type. |
| one_file | defines weather it is a header from one or two files image. |
Basic Constructor.
| img | base image to extract dimensions and datatype. |
| one_file | defines weather it is a header from one or two files image. |
| Bial::NiftiHeader::NiftiHeader | ( | const std::string & | filename | ) |
Basic Constructor.
| filename | File name. |
Assigns mat data to stm.
| mat | a matrix to be set to affine transformation matrix. |
| Matrix< float > Bial::NiftiHeader::AffineMatrix | ( | ) | const |
returns a copy of stm.
| none. |
|
static |
Returns true if coronal dimension direction is anterior-posterior.
| orientation | Image orientation. Must be a composition of three values containing: LR, RL, SI, IS, AP, or PA. Look for NiftiHeader::Orientation() function for examples. |
|
static |
Returns the number of the image dimension that corresponds to axial direction.
| orientation | Image orientation. Must be a composition of three values containing: LR, RL, SI, IS, AP, or PA. Look for NiftiHeader::Orientation() function for examples. |
| short Bial::NiftiHeader::BitPix | ( | ) | const |
Returns the number of bits per pixel.
| none. |
|
static |
Returns the number of the image dimension that corresponds to coronal direction.
| orientation | Image orientation. Must be a composition of three values containing: LR, RL, SI, IS, AP, or PA. Look for NiftiHeader::Orientation() function for examples. |
|
static |
Returns nifti data file name associated to filename.
| filename | A nifti extension file name. |
| NiftiType Bial::NiftiHeader::DataType | ( | ) | const |
Returns data type code.
| none. |
| void Bial::NiftiHeader::DataType | ( | NiftiType | type | ) |
Changes header information to support data of type 'type'.
| type | data type. |
Returns the type of the data in given file.
| filename | A nifti extension file name. |
|
static |
Computes the number of bytes of each element and the bytes to be swapped.
| datatype | type of image data. |
| nbyper | bytes by data element. |
| swapsize | size of datas that may be swapped. |
Returns a reference to dimension vector.
| none. |
|
static |
Returns existing nifti data file name associated to filename.
| filename | A nifti extension file name. |
|
static |
Returns existing nifti header file name associated to filename.
| filename | A nifti extension file name. |
|
static |
Returns nifti header file name associated to filename.
| filename | A nifti extension file name. |
|
static |
Returns true if given file has nifti extension.
| filename | A file name. |
|
static |
Verifies if header nifti file corresponding to filename must swap bytes order.
| filename | File name. |
| void Bial::NiftiHeader::MatToQuatern | ( | ) |
Translates 4x4 matrix used to convert from xyz to ijk space to quaterns.
| none. |
| std::string Bial::NiftiHeader::Orientation | ( | size_t | row | ) | const |
Returned std::string can be: LR, RL, SI, IS, AP, PA, or Undefined.
| row | The row of orientation. |
| std::string Bial::NiftiHeader::Orientation | ( | ) | const |
Returned std::string will be a composition of three values containing: LR, RL, SI, IS, AP, or PA, or Undefined std::string.
| none. |
Returns a reference to pixel dimension vector.
| none. |
| float Bial::NiftiHeader::PixelSize | ( | size_t | dms | ) | const |
Returns the pixel size of a given image dimension.
| dms | The dimension of desired pixel size. |
| void Bial::NiftiHeader::PixelSize | ( | size_t | dms, |
| float | val | ||
| ) |
Updates Pixel dimension size.
| dms | The dimension of desired size. |
| val | New size of the pixel dimension. |
| O& Bial::NiftiHeader::Print | ( | O & | os | ) | const |
Prints nifti header information to output stream 'os'.
| os | An output stream. |
| O& Bial::NiftiHeader::PrintOrientation | ( | O & | os | ) | const |
Prints nifti orientation information to output stream 'os'.
| os | An output stream. |
Assigns mat data to qtm.
| mat | a matrix to be set to quatern matrix. |
| Matrix< float > Bial::NiftiHeader::QuaternMatrix | ( | ) | const |
returns a copy of qtm.
| none. |
| void Bial::NiftiHeader::QuaternOffset | ( | float | x, |
| float | y, | ||
| float | z | ||
| ) |
Sets quatern offset.
| x | x quatern offset. |
| y | y quatern offset. |
| z | z quatern offset. |
Translates quaterns to 4x4 matrix used to convert from xyz to ijk space.
| pixel_dim | dimensions of the pixel. |
|
static |
Returns a nifti header read from file with filename 'filename'.
| filename | A nifti extension file name. |
|
static |
Returns the number of the image dimension that corresponds to sagittal direction.
| orientation | Image orientation. Must be a composition of three values containing: LR, RL, SI, IS, AP, or PA. Look for NiftiHeader::Orientation() function for examples. |
| size_t Bial::NiftiHeader::Size | ( | size_t | dms | ) | const |
Returns the size of a given image dimension.
| dms | The dimension of desired size. |
| void Bial::NiftiHeader::Size | ( | size_t | dms, |
| size_t | val | ||
| ) |
Updates image dimension size.
| dms | The dimension of desired size. |
| val | New size of the dimension. |
|
static |
Returns true if axial dimension direction is superior-inferior.
| orientation | Image orientation. Must be a composition of three values containing: LR, RL, SI, IS, AP, or PA. Look for NiftiHeader::Orientation() function for examples. |
|
static |
Swaps bytes of data pointed by ar. Used to read data written by different architectures.
| n | number of bytes to be swapped. |
| siz | size of the swapped data. |
| ar | pointer to data. |
| bool Bial::NiftiHeader::UseAffine | ( | ) |
Returns a boolean value indicating if this MR image uses affine orientation form or not.
| none. |
| bool Bial::NiftiHeader::UseQuatern | ( | ) |
Returns a boolean value indicating if this MR image uses quaternion orientation form or not.
| none. |
| void Bial::NiftiHeader::Write | ( | OFile & | file, |
| bool | one_file | ||
| ) | const |
Writes this nifti header to file.
| file | Opened file for outputting. |
| one_file | If it is nii or hdr+img file. |
| void Bial::NiftiHeader::Write | ( | const std::string & | filename | ) | const |
Writes this nifti header to file with filename 'filename'.
| filename | A nifti extension file name. |
|
friend |
Definition at line 250 of file NiftiHeader.hpp.
|
static |
Definition at line 253 of file NiftiHeader.hpp.
|
static |
Definition at line 252 of file NiftiHeader.hpp.


{% extends "base.html" %} {% block title %}Home{% endblock %} {% block head %} {{ super() }} {% endblock %} {% set active_page = "home" %} {% block content %}
Awesome!  Yes, let's do that. There are so many things that still can be improved.
This is the repository on GitHub: allmysubs on github
New, short term, ideas will end up in the issue tracker. On the long run, I could imagine apps that "fix" the notification system for YouTube from the viewers perspective, and also a web application with more features. Features that I would love to see include:


You proceed to payment if there are no problems with your order, click Go Back to return to the home page to shop for more should you wish to.
NFB sees itself to be the leader in providing A-class services and products to its customers through the use of technology, in this market. Northern Fame Bookstore (NFB) is best known for being the favourite Malaysian local retail and distributor for all kinds of books. They do serve walk-in customers as well in their shop located at Bukit Jalil, Malaysia.
Nothern Fame Bookstore © Copyright 2016 Jason Khor


I am a coder. I make free stuff for people to enjoy. I made such brilliant inventions as XCollector... and that's it. BUT I do intend to put out more free stuff for you guys. You are welcome.


Algorithms are precise step-by-step instructions on how to accomplish a desired task.
Find the Greatest Common Divisor of two natural numbers Positive integers (a,b)
<gcd-code>
## Algorithm
While b!=0
t=b
b=a mod b
a=t
return a
</gcd-code>
Binary search is like looking up a phone number or a word in the dictionary
<binarysearch>
## Algorithm
If ( value == middle element )
value is found
else if ( value < middle element )
search left-half of list with the same method
else
search right-half of list with the same method
</binarysearch>
<binarysearch>
## Algorithm
Case 1: val == a[mid]
val = 10
low = 0, high = 8
mid = (0 + 8) / 2 = 4
</binarysearch>
<binarysearch>
## Algorithm
Case 2: val > a[mid]
val = 19
low = 0, high = 8
mid = (0 + 8) / 2 = 4
new low = mid+1 = 5
</binarysearch>
<binarysearch>
## Algorithm
Case 3: val < a[mid]
val = 7
low = 0, high = 8
mid = (0 + 8) / 2 = 4
new high = mid-1 = 3
</binarysearch>
The Idea of the insertion sort is similer to the Idea of sorting the Playing cards .
<insertionsort>
## Algorithm
INSERTION-SORT (A)
1 for j <- 2 to length[A]
2 do key <- A[j]
3 Insert A[j] into the sorted sequence A[1 . . j - 1].
4 i <- j - 1
5 while i > 0 and A[i] > key
6 do A[i + 1] <- A[i]
7 i <- i - 1
8 A[i + 1] <- key
</insertionsort>


Access Control
Add role based permissions to your documents.
The Access Control extension allows you to set user access permissions on a document with simple annotations.
Configuration
Access Control has no configuration options. Just use:
$manifest = new Zoop\Shard\Manifest([ ... 'extension_configs' => [ 'extension.accessControl' => true ], ... ]);
However, Access Control requires a configured user
service which is an instance of Zoop\Common\User\RoleAwareUserInterface
. See User Config
Annotations
@Shard\AccessControl
The @Shard\AccessControl
annotation is a document annotation that can contain a list of permission annotations which define who can access the document and what level of access they have. Eg:
/** * @ODM\Document * @Shard\AccessControl({ * ... * }) */ class MyDoc {...}
@Shard\Permission\Basic
The Access Control extension provides the Basic permission. (Other extensions may provide other kinds of permission.) The Basic permission has three arguments:
| Name | type | default | description |
|---|---|---|---|
| allow | string | array | null | A role, or array of roles that are allowed. |
| roles | string | array | null | A role, or array of roles that the permission applies to. |
| allow | string | array | null | An action, or array of actions that are allowed. |
| deny | string | array | null | An action, or array of actions that are denied. |
Access Control defines four actions (other extensions may define further actions):
| Name | description |
|---|---|
| create | Persist a new instance of the document to the database. |
| read | Read documents of this type from the database. |
| update::$field | Change fields on an instance of this document which has already been persisted. |
| delete | Perminently delete this type of document from the database. |
So, for example, the following annotations would allow users with the guest
permission to create
, and read
.
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Zoop\Shard\Annotation\Annotations as Shard; /** * @ODM\Document * @Shard\AccessControl({ * @Shard\Permission\Basic(roles="guest", allow={"create", "read"}) * }) */ class Simple {...}
Events
Most access control checks happen during a $documentManager->flush()
. Therefore, when an access control check fails, an exception is not raised, as that would prevent a flush from completing correctly. Rather, an event is raised. The following events may be listened to:
| Name | description |
|---|---|
| createDenied | Fires if create is attempted and denied. |
| updateDenied | Fires if update is attempted and denied. |
| deleteDenied | Fires if delete is attempted and denied. |
Note: there is no event for a rejected read
. This is because read access control is achieved through query filters, meaning both Doctrine and Shard are unaware if, or how many documents may have been filtered out by read access control.
Default permission
If a permission is not allowed, then it is always denied.
So, in this example there isn't any user who can update
or delete
.
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Zoop\Shard\Annotation\Annotations as Shard; /** * @ODM\Document * @Shard\AccessControl({ * @Shard\Permission\Basic(roles="guest", allow={"create", "read"}) * }) */ class Simple {...}
The * wildcard
The *
can be used to glob role or action names.
In this example all users are allowed to read, editors are also allowed to create, and admins can do everything.
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Zoop\Shard\Annotation\Annotations as Shard; /** * @ODM\Document * @Shard\AccessControl({ * @Shard\Permission\Basic(roles="*", allow="read"), * @Shard\Permission\Basic(roles="editor", allow="create"), * @Shard\Permission\Basic(roles="admin", allow="*") * }) */ class Simple {...}
Specific actions take precidence over wild cards in the same Permission. Eg, editors are allowed to all actions except delete
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Zoop\Shard\Annotation\Annotations as Shard; /** * @ODM\Document * @Shard\AccessControl({ * @Shard\Permission\Basic(roles="editor", allow="*", deny="delete") * }) */ class Simple {...}
Order of permissions
Permissions are read in the order they are listed, so permissions lower on the list can override permissions higher on the list. Eg, if a user with the role editor
tries to create
they will be allowed, because the later permission overrides the earlier permission.
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Zoop\Shard\Annotation\Annotations as Shard; /** * @ODM\Document * @Shard\AccessControl({ * @Shard\Permission\Basic(roles={"guest", "editor"}, allow="read"), * @Shard\Permission\Basic(roles="editor", allow="create") * }) */ class Simple {...}
Users with multiple roles
Users may have more than one role. Eg, if a user has only the editor role, they they will be allowed to create, but not be allowed to read. If a user has both the guest and editor role, they will be allowed to read and create.
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Zoop\Shard\Annotation\Annotations as Shard; /** * @ODM\Document * @Shard\AccessControl({ * @Shard\Permission\Basic(roles="guest", allow="read"), * @Shard\Permission\Basic(roles="editor", allow="create") * }) */ class Simple {...}
Update actions
Update actions are related to individual fields, not whole documents. To allow all fields to be updated, use the *
wildcard. Eg:
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Zoop\Shard\Annotation\Annotations as Shard; /** * @ODM\Document * @Shard\AccessControl({ * @Shard\Permission\Basic(roles="editor", allow="update::*") * }) */ class Simple {...}
To allow update on a specific field, use the field name. Eg:
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Zoop\Shard\Annotation\Annotations as Shard; /** * @ODM\Document * @Shard\AccessControl({ * @Shard\Permission\Basic(roles="editor", allow="update::description") * }) */ class Simple {...}
To allow update on all fields, except some:
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Zoop\Shard\Annotation\Annotations as Shard; /** * @ODM\Document * @Shard\AccessControl({ * @Shard\Permission\Basic(roles="editor", allow="update::*", deny={"update::lockedField1", "update::lockedField2"}) * }) */ class Simple {...}
Access Controller Service
Use the Access Controller service's areAllowed
method to check if the configured user has permission to do actions on a document.
AccessController::areAllowed arguments
| Name | type | description |
|---|---|---|
| actions | array | An array of action names to check. |
| metadata | ClassMetadata | The metadata for the document type being checked. This argument doesn't have to be passed, but is required if checking the create action, because no document instance exists before it is created. |
| document | Object | A document instance to check permissions against. Not required when checking create action. |
This method will return an AllowedResult object.
For example:
$accessController = $manifest->getServiceManager->get('accessController'); if ( ! $accessController->areAllowed('update::name', null, $mydocument)->getAllowed()){ //configured user is not allowed to update the name field of $mydocument; }
Annotations
Event based annotation handling.
The Annotation Extension is a low level extension that handles reading all the @Shard
annotations. It is automatically enabled by any extension that requires annotations, so it can normally be ignored.
Crypt
Hash or encrypt document fields.
Configuration
Access Control has no configuration options. Just use:
$manifest = new Zoop\Shard\Manifest([ ... 'extension_configs' => [ 'extension.crypt' => true ], ... ]);
Hash
A hash is a one way encryption method. That is, once the text is encrypted, you can't get the plain text back. It is especially useful for user passwords.
@Shard\Crypt\Hash
To hash a field, just add the @Shard\Crypt\Hash
annotation to that field. Eg:
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Zoop\Shard\Annotation\Annotations as Shard; class MyDocument { /** * @ODM\String * @Shard\Crypt\Hash */ protected $password; ... }
Hash Salt
It is wise to use a salt when hashing to make cracking the encryption harder.
Salt stored in Document
By default, the crypt extension will check if your document implements Zoop\Common\Crypt\SaltInterface
. If so, that will be used to retireve a salt. Eg:
use Zoop\Common\Crypt\SaltInterface; use Zoop\Shard\Crypt\SaltGenerator; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Zoop\Shard\Annotation\Annotations as Shard; class MyDocument implements SaltInterface { /** * @ODM\String * @Shard\Crypt\Hash */ protected $password; /** * @ODM\String */ protected $salt; public function getSalt(){ if (!isset($this->salt)){ $this->salt = SaltGenerator::generateSalt(); } return $this->salt; } ... }
Note: if there are several hashed fields in the one document, this method will use the same salt for all.
Alternate salt
If you want to use a different salt, set the salt
property of the annotation to a service name that will return an instance of Zoop\Common\Crypt\SaltInterface
. Eg
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Zoop\Shard\Annotation\Annotations as Shard; class MyDocument { /** * @ODM\String * @Shard\Crypt\Hash(salt='mysaltservice') */ protected $password; ... }
And configure your salt service in the Manifest:
$manifest = new Zoop\Shard\Manifest([ 'service_manager_config' => [ 'invokables' => [ 'mysaltservice' => 'My\Salt' //A class that implements SaltInterface ] ] ]);
Alternate Hash Algorithim
The default hash algorithim is in Zoop\Shard\Crypt\Hash\BasicHashService
. If you would like to use an alternate hashing algorithim, set the service
property of the annotation to a service name that will return an instance of Zoop\Shard\Crypt\Hash\HashServiceInterface
. Eg:
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Zoop\Shard\Annotation\Annotations as Shard; class MyDocument { /** * @ODM\String * @Shard\Crypt\Hash(service='myhashservice') */ protected $password; ... }
And configure your hash service in the Manifest:
$manifest = new Zoop\Shard\Manifest([ 'service_manager_config' => [ 'invokables' => [ 'myhashservice' => 'My\Hash\Service' //A class that implements HashServiceInterface ] ] ]);
Block Cipher
A block cipher is a two way encryption method. That is, once the text is encrypted, you can get the plain text back.
@Shard\Crypt\BlockCipher
To encrypt a field, just add the @Shard\Crypt\BlockCipher
annotation to that field. You must also set the name of a key service. Eg:
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Zoop\Shard\Annotation\Annotations as Shard; class MyDocument { /** * @ODM\String * @Shard\Crypt\BlockCipher(key="mykey") */ protected $password; ... }
Key Service
The key is used to encrypt and decrypt the field. Keep your keys safe! If someone steals your keys, then they can unlock your data.. The key is set with a key service which must return an instance of Zoop\Common\Crypt\KeyInterface
. Eg:
$manifest = new Zoop\Shard\Manifest([ 'service_manager_config' => [ 'invokables' => [ 'mykey' => 'My\Key' //A class that implements KeyInterface ] ] ]);
use Zoop\Common\Crypt\KeyInterface; class Key implements KeyInterface { public function getKey() { return 'my very secret key phrase'; } }
Block Cipher Salt
If you want to use a salt with the Block Cipher, you can.
Salt stored in Document
By default, the crypt extension will check if your document implements Zoop\Common\Crypt\SaltInterface
. If so, that will be used to retireve a salt. Eg:
use Zoop\Common\Crypt\SaltInterface; use Zoop\Shard\Crypt\SaltGenerator; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Zoop\Shard\Annotation\Annotations as Shard; class MyDocument implements SaltInterface { /** * @ODM\String * @Shard\Crypt\Hash */ protected $password; /** * @ODM\String */ protected $salt; public function getSalt(){ if (!isset($this->salt)){ $this->salt = SaltGenerator::generateSalt(); } return $this->salt; } ... }
Note: if there are several encrypted fields in the one document, this method will use the same salt for all.
Alternate salt
If you want to use a different salt, set the salt
property of the annotation to a service name that will return an instance of Zoop\Common\Crypt\SaltInterface
. Eg
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Zoop\Shard\Annotation\Annotations as Shard; class MyDocument { /** * @ODM\String * @Shard\Crypt\BlockCypter(key='mykey', salt='mysaltservice') */ protected $password; ... }
And configure your salt service in the Manifest:
$manifest = new Zoop\Shard\Manifest([ 'service_manager_config' => [ 'invokables' => [ 'mykey' => 'My\Key', 'mysaltservice' => 'My\Salt' //A class that implements SaltInterface ] ] ]);
Alternate Encryption Algorithim
The default block cypher algorithim is in Zoop\Shard\Crypt\BlockCypher\ZendBlockCypherService
. If you would like to use an alternate algorithim, set the service
property of the annotation to a service name that will return an instance of Zoop\Shard\Crypt\BlockCypher\BlockCypherServiceInterface
. Eg:
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Zoop\Shard\Annotation\Annotations as Shard; class MyDocument { /** * @ODM\String * @Shard\Crypt\BlockCypher(key="mykey", service='mycipherservice') */ protected $password; ... }
And configure your service in the Manifest:
$manifest = new Zoop\Shard\Manifest([ 'service_manager_config' => [ 'invokables' => [ 'mykey' => 'My\Key', 'mycipherservice' => 'My\Cipher\Service' //A class that implements BlockCipherServiceInterface ] ] ]);
Freeze
Freeze documents against updating or deleting.
Configuration
Freeze has no configuration options. Just use:
$manifest = new Zoop\Shard\Manifest([ ... 'extension_configs' => [ 'extension.freeze' => true ], ... ]);
Making a document freezable
To make a document freezable, a boolean field should be annotated with @Shard\Freeze
. Eg:
/** * @ODM\Boolean * @Shard\Freeze */ protected $frozen = false;
For convienence you can use the Zoop\Shard\Freeze\DataModel\FreezableTrait
to add such a field to a document. Eg:
use Zoop\Shard\Freeze\DataModel\FreezeableTrait; //Annotation imports use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Zoop\Shard\Annotation\Annotations as Shard; /** @ODM\Document */ class MyDocument { use FreezeableTrait; ... }
Using the Freezer service
The freezer can be used to freeze and thaw documents. When frozen they cannot be updated or deleted. Note that the frozen state is not persisted until the DocumentManager is flushed. Eg:
$freezer = $manifest->getServiceManager()->get('freezer'); //get the freezer service $freezer->freeze($myDocument); //freeze a document $freezer->thaw($anotherDocument); //thaw a document $manifest->getServiceManager()->get('mydocumentmanager')->flush() //flush to persist changes
Freeze and Thaw stamps
Timestamps
The freeze extension support automatic timestamping of freeze and thaw events. Use the @Shard\Freeze\FrozenOn
and @Shard\Freeze\ThawedOn
annotations. Eg:
/** * @ODM\Timestamp * @Shard\Freeze\FrozenOn */ protected $frozenOn; /** * @ODM\Timestamp * @Shard\Freeze\ThawedOn */ protected $thawedOn;
Alternately you can use traits. Eg
use Zoop\Shard\Freeze\DataModel\FreezeableTrait; use Zoop\Shard\Freeze\DataModel\FreezenOnTrait; use Zoop\Shard\Freeze\DataModel\ThawedOnTrait; //Annotation imports use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Zoop\Shard\Annotation\Annotations as Shard; /** @ODM\Document */ class MyDocument { use FreezeableTrait; use FrozenOnTrait; use ThawedOnTrait; ... }
The values of the fields can be retrieved with:
$myDocument->getFrozenOn(); $myDocument->getThawedOn();
User stamps
The freeze extension support automatic stamping with the active username on freeze and thaw events. Use the @Shard\Freeze\FrozenBy
and @Shard\Freeze\ThawedBy
annotations. This requires a configured user. Eg:
/** * @ODM\String * @Shard\Freeze\FrozenBy */ protected $frozenBy; /** * @ODM\String * @Shard\Freeze\ThawedBy */ protected $thawedBy;
Alternately you can use traits. Eg
use Zoop\Shard\Freeze\DataModel\FreezeableTrait; use Zoop\Shard\Freeze\DataModel\FreezenByTrait; use Zoop\Shard\Freeze\DataModel\ThawedByTrait; //Annotation imports use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Zoop\Shard\Annotation\Annotations as Shard; /** @ODM\Document */ class MyDocument { use FreezeableTrait; use FrozenByTrait; use ThawedByTrait; ... }
The values of the fields can be retrieved with:
$myDocument->getFrozenBy(); $myDocument->getThawedBy();
Access Conntrol
The Freeze extension can hook into the Access Control extension to allow or deny roles to the freeze
and thaw
actions. This requires the Access Control extension to be enabled, as well as the Freeze extension. Eg:
$manifest = new Zoop\Shard\Manifest([ ... 'extension_configs' => [ 'extension.accessControl' => true, 'extension.freeze' => true ], ... ]);
Permissions can then be used as normal with the added actions of freeze
and thaw
. Eg:
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Zoop\Shard\Annotation\Annotations as Shard; /** * @ODM\Document * @Shard\AccessControl({ * @Shard\Permission\Basic(roles="editor", allow="freeze", deny="thaw") * ... * }) */ class Simple {...}
Freeze Filter
The freeze extension provides a filter that can be used to remove frozen documents from result sets.
To filter out all frozen documents, use:
$documentManager->getFilterCollection()->enable('freeze');
To filter so only frozen documents are returned use:
$documentManager->getFilterCollection()->enable('freeze'); $filter = $documentManager->getFilterCollection()->getFilter('freeze'); $filter->onlyFrozen();
Events
Freeze provides the following events which can be subscribed to with the Doctrine EventManager:
| Name | description |
|---|---|
| preFreeze | Fires before freeze happens. |
| postFreeze | Fires after freeze happens. |
| preThaw | Fires before thaw happens. |
| postThaw | Firest after thaw happens. |
| freezeDenied | Fires if a freeze is attempted but denied by access control. |
| thawDenied | Fires if a thaw is attempted by denied by access control. |
| frozenUpdateDenied | Fires if attempt is made to update a frozen document. |
| frozenDeleteDenied | Fires if attempt is made to delete a frozen document. |
Generator
Dynamically generate new resources based on document classes
The generator extension can be used to dynamically generate resources such as help files, javascript, and api documentation, from your document classes.
Configuration
Configuration is very important for the Generator extension. A resource_map
must be defined. A resource_map
is an array of resources that can be generated by the generator extension. The array keys are the resource names.
$manifest = new Zoop\Shard\Manifest([ ... 'extension_configs' => [ 'extension.generator' => [ 'my resource name' => [ /* resource generator config goes here */ ] ] ], ... ]);
The configuration array for a resource may have three keys:
| Name | type | required | description |
|---|---|---|---|
| generator | string | true | The service name which will return an instance of Zoop\Shard\Generator\GeneratorInterface |
| class | string | true | The class name of a document class that will be used to generate the resource. |
| options | array | false | An array of options that will be passed to the generator. |
A complete config might look like:
$manifest = new Zoop\Shard\Manifest([ ... 'extension_configs' => [ 'extension.generator' => [ 'userDescription.html' => [ 'generator' => 'my.description.generator', 'class' => 'My\Documents\User', 'options' => [ 'theme' => 'ocean_blue' ] ] ] ], ... ]);
The Resource Map
The resource map is a service provided by the generator extension. To get it use:
$resourceMap = $manifest->getServiceManager()->get('resourceMap');
To check if a resource can be generated:
if ($resourceMap->has('userDescription.html')){ //resource can be generated } else { //resource can't be generated };
To generate a resource:
$html = $resourceMap->get('userDescription.html');
Create your own generator
To create your own generator, just implement Zoop\Shard\Generator\GeneratorInterface
. Eg:
namespace My; use Zoop\Shard\Generator\GeneratorInterface; class DescriptionGenerator implements GeneratorInterface { public function generate($name, $class, $options = null) { return "You requested resource $name for $class be generated
"; } }
You will also need to register your generator with the service manager. This is most easily done when configuring the Manifest. Eg:
$manifest = new Zoop\Shard\Manifest([ ... 'extension_configs' => [ 'extension.generator' => [ ... ] ], 'service_manager_config' => [ 'invokables' => [ 'my.description.generator' => 'My\DescriptionGenerator' ], ... ] ]);
Owner
Add an owner field to documents, and enable the owner based access control.
Configuration
Owner has no configuration options. Just use:
$manifest = new Zoop\Shard\Manifest([ ... 'extension_configs' => [ 'extension.owner' => true ], ... ]);
However, the Owner extension requires a configured user
service which is an instance of Zoop\Common\User\UserInterface
. See User Config
Add an owner field
Place the @Shard\Owner
annotation on a field.
/** * @ODM\String * @Shard\Owner */ protected $owner;
Alternately you can use traits. Eg
use Zoop\Shard\Owner\DataModel\OwnerTrait; //Annotation imports use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Zoop\Shard\Annotation\Annotations as Shard; /** @ODM\Document */ class MyDocument { use OwnerTrait; ... }
The values of the field can be set and retrieved with:
$myDocument->setOwner(); $myDocument->getOwner();
Note: the value of the owner field is not automatically assigned to the active use when a document is created. It must be manually set.
Owner based access control
If the Access Control extension is enabled along with the Owner extension, the owner
role can be used to allow or deny actions if the current user is equal to the owner field.
For example, the following access control annotations, only the owning user may read the document.
/** * @ODM\Document * @Shard\AccessControl({ * @Shard\Permission\Basic(roles="owner", allow="read") * }) */
Access control owner field update
It is normally required to access control the ability to change who owns a document. Eg:
/** * @ODM\Document * @Shard\AccessControl({ * @Shard\Permission\Basic(roles="*", allow={"create", "read"} ), * @Shard\Permission\Basic(roles="owner", allow="update::*", deny="update::owner"), * @Shard\Permission\Basic(roles="admin", allow="update::owner" ) * }) */
In this example, all roles can read. Only the own can update a document. And only an admin can update the document owner.
Serializer
Serialize document instances to array or json, and unserialize back to document instances.
The shard Serializer offers fine grained control over how documents are serialized and unserialized, with particluar mind to ajax and web clients.
Configuration
The serializer does not require any specific configuration.
$manifest = new Zoop\Shard\Manifest([ ... 'extension_configs' => [ 'extension.serializer' => true ], ... ]);
However, some configuration options are available:
$manifest = new Zoop\Shard\Manifest([ ... 'extension_configs' => [ 'extension.serializer' => [ 'type_serializers' => [...] 'max_nesting_depth' => [...] ] ], ... ]);
| Name | type | default | description |
|---|---|---|---|
| type_serializer | array | ['date' => 'serializer.type.dateToISO8601'] | An array of type serializers. For more information see below. |
| max_nesting_depth | integer | 1 | How deeply should the tree of references inside documents be followed when serializing. |
Serializing Documents
First get the Serializer service, and then it can be used to serialize documents:
$serializer = $manifest->getServiceManager()->get('serializer'); $array = $serializer->toArray($myDocument); //serialize to array $json = $serializer->toJson($myDocument); //serialize to json
@Shard\Serializer\Ignore and @Shard\Unserializer\Ignore
Place on a document field to control if the field is serialized
Always ignore the field, eg:
/** * @ODM\String */ protected MyProperty; /* or */ /** * @ODM\String * @Shard\Serializer\Ignore * @Shard\Unserializer\Ignore */ protected MyProperty;
Ignore a field only when serializing (not when unserializing):
/** * @ODM\String * @Shard\Serializer\Ignore */ protected MyProperty;
Ignore a field only when unserializing (not when serializing):
/** * @ODM\String * @Shard\Unserializer\Ignore */ protected MyProperty;
Reference Serializers
Document references can be serialized in several differnet ways.
RefLazy
By default references will be serialized to an array like this:
[$ref: 'CollectionName/DocumentId']
The $ref
style of referencing is what Mongo uses internally.
The default behaviour uses the RefLazy serializer. However this can be overridden by defineing an alternative ReferenceSerializer as a property annotation.
Two alternate ReferenceSerializers are already included with Shard.
SimpleLazy
SimpleLazy will serialize a reference as the mongo id. It can be used like this:
/** * @ODM\ReferenceMany(targetDocument="MyTargetDocument") * @Sds\Serializer\SimpleLazy */ protected $myDocumentProperty;
Eager
Eager will serialize references as if they were embedded documents. It can be used like this:
/** * @ODM\ReferenceMany(targetDocument="MyTargetDocument") * @Sds\Serializer\Eager */ protected $myDocumentProperty;
When using the Eager serializer, the maxNestingDepth configuration option will control how deep the Eager serializer will go into a tree of references.
Custom Reference Serializer
You can create your own reference serializer to render references however you like. To do so, implement the Shard\Serializer\Reference\ReferenceSerializerInterface
.
Then register your serializer with the service manager in the manifest config:
$manifest = new Zoop\Shard\Manifest([ ... 'extension_configs' => [ 'extension.serializer' => [ ... ] ], 'service_manager_config' => [ 'invokables' => [ 'my.reference.serializer' => 'My\ReferenceSerializer\Class' ], ... ] ]);
To use your reference serializer, use the annotation:
/** * @ODM\ReferenceMany(targetDocument="MyTargetDocument") * @Sds\Serializer\ReferenceSerializer("my.reference.serializer") */ protected $myDocumentProperty;
Date Serializer
Fields of type date
are serialized by default with Shard\Serializer\Type\DateToISO8601
.
To override this format, see Custom Type Serializers below
Custom Type Serializers
Each document field has an associated type, such as string or date. Serialization may be customized by type.
First create a class which implements the Shard\Serializer\Type\TypeSerializerInterface
. You will need to define serialize and unserialize methods.
For example, this class will uppercase the first letter of every string when serializing, and lower case the first letter when unserializing:
use Shard\Serializer\Type\TypeSerializerInterface; class MyStringSerializer implements TypeSerializerInterface { public static function serialize($value) { return ucfirst($value); } public static function unserialize($value) { return lcfirst($value); } }
Then the class needs to be registered in the extension config and service manager:
$manifest = new Zoop\Shard\Manifest([ ... 'extension_configs' => [ 'extension.serializer' => [ 'type_serializers' => [ 'string' => 'my.string.serializer' ] ] ], 'service_manager_config' => [ 'invokables' => [ 'my.string.serializer' => 'MyStringSerializer' ], ... ] ]);
The default Date serializer is an example of a Type Serializer which is regisered by default. To over ride it, simply register your own in the extension config.
Unserializing Documents
Get the unserializer from the service manager:
$unserializer = $manifest->getServiceManager()->get('unserializer');
Both fromArray
and fromJson
will unserialize an array or json into a document. They take up to four arguments:
| Name | type | default | description |
|---|---|---|---|
| data | array | string | The data to be unserialized. An array for fromArray , or a json string for fromJson . |
|
| className | string | null | The class name of the document instance to create. |
| document | object | null | If supplied, the unserializer won't attempt to load any document from the db, but use this one instead. |
| mode | string | unserialize_patch | Must be either unserialize_update or unserialize_patch . If unserialize_update is used, the unserialized document will replace any existing document in the db with the same id. If unserialize_patch is used the unserialized data will be merged with any existing document in the db. |
Soft Delete
Mark documents as deleted, without actually deleting them.
Soft Deleted documents are simply marked as soft deleted, so they can be filtered out from result sets. Soft Deleted documents cannot be updated. However, note that Soft Deleted documents can still be fully deleted. If you need to control delete access, then use the Access Control extension.
Configuration
Soft Delete has no configuration options. Just use:
$manifest = new Zoop\Shard\Manifest([ ... 'extension_configs' => [ 'extension.softDelete' => true ], ... ]);
Making a document soft deletable
To make a document soft deleteable, a boolean field should be annotated with @Shard\SoftDelete
. Eg:
/** * @ODM\Boolean * @Shard\SoftDelete */ protected $softDeleted = false;
For convienence you can use the Zoop\Shard\SoftDelete\DataModel\SoftDeletableTrait
to add such a field to a document. Eg:
use Zoop\Shard\SoftDelete\DataModel\SoftDeletableTrait; //Annotation imports use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Zoop\Shard\Annotation\Annotations as Shard; /** @ODM\Document */ class MyDocument { use SoftDeletableTrait; ... }
Using the SoftDeleter service
The SoftDeleter can be used to soft delete and restore documents. Note that the soft delete state is not persisted until the DocumentManager is flushed. Eg:
$softDeleter = $manifest->getServiceManager()->get('softDeleter'); //get the softDeleter service $softDeleter->softDelete($myDocument); //soft delete a document $softDeleter->restore($anotherDocument); //restore a document $manifest->getServiceManager()->get('mydocumentmanager')->flush() //flush to persist changes
Soft Delete and Restore stamps
Timestamps
The soft delete extension supports automatic timestamping of soft delete and restore events. Use the @Shard\SoftDelete\SoftDeletedOn
and @Shard\SoftDelete\RestoredOn
annotations. Eg:
/** * @ODM\Timestamp * @Shard\SoftDelete\SoftDeletedOn */ protected $softDeletedOn; /** * @ODM\Timestamp * @Shard\SoftDelete\RestoredOn */ protected $restoredOn;
Alternately you can use traits. Eg
use Zoop\Shard\SoftDelete\DataModel\SoftDeletableTrait; use Zoop\Shard\SoftDelete\DataModel\SoftDeletedOnTrait; use Zoop\Shard\SoftDelete\DataModel\RestoredOnTrait; //Annotation imports use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Zoop\Shard\Annotation\Annotations as Shard; /** @ODM\Document */ class MyDocument { use SoftDeletableTrait; use SoftDeletedOnTrait; use RestoredOnTrait; ... }
The values of the fields can be retrieved with:
$myDocument->getSoftDeletedOn(); $myDocument->getRestoredOn();
User stamps
The soft delete extension supports automatic stamping with the active username on soft delete and restore events. Use the @Shard\SoftDelete\SoftDeletedBy
and @Shard\SoftDelete\RestoredBy
annotations. This requires a configured user. Eg:
/** * @ODM\String * @Shard\SoftDelete\SoftDeletedBy */ protected $softDeletedBy; /** * @ODM\String * @Shard\SoftDelete\RestoredBy */ protected $restoredBy;
Alternately you can use traits. Eg
use Zoop\Shard\SoftDelete\DataModel\SoftDeleteableTrait; use Zoop\Shard\SoftDelete\DataModel\SoftDeletedByTrait; use Zoop\Shard\SoftDelete\DataModel\RestoredByTrait; //Annotation imports use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Zoop\Shard\Annotation\Annotations as Shard; /** @ODM\Document */ class MyDocument { use SoftDeleteableTrait; use SoftDeletedByTrait; use RestoredByTrait; ... }
The values of the fields can be retrieved with:
$myDocument->getSoftDeletedBy(); $myDocument->getRestoredBy();
Access Conntrol
The soft deleted extension can hook into the Access Control extension to allow or deny roles to the softDelete
and restore
actions. This requires the Access Control extension to be enabled, as well as the Soft Delete extension. Eg:
$manifest = new Zoop\Shard\Manifest([ ... 'extension_configs' => [ 'extension.accessControl' => true, 'extension.softDelete' => true ], ... ]);
Permissions can then be used as normal with the added actions of softDelete
and restore
. Eg:
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Zoop\Shard\Annotation\Annotations as Shard; /** * @ODM\Document * @Shard\AccessControl({ * @Shard\Permission\Basic(roles="editor", allow="softDelete", deny="restore") * ... * }) */ class Simple {...}
Soft Delete Filter
The soft delete extension provides a filter that can be used to remove soft deleted documents from result sets.
To filter out all soft deleted documents, use:
$documentManager->getFilterCollection()->enable('softDelete');
To filter so only soft deleted documents are returned use:
$documentManager->getFilterCollection()->enable('softDelete'); $filter = $documentManager->getFilterCollection()->getFilter('softDelete'); $filter->onlySoftDeleted();
Events
Soft Delete provides the following events which can be subscribed to with the Doctrine EventManager:
| Name | description |
|---|---|
| preSoftDelete | Fires before soft delete happens. |
| postSoftDelete | Fires after soft delete happens. |
| preRestore | Fires before restore happens. |
| postRestore | Firest after restore happens. |
| softDeleteDenied | Fires if a soft delete is attempted but denied by access control. |
| restoreDenied | Fires if a restore is attempted by denied by access control. |
| softDeleteUpdateDenied | Fires if attempt is made to update a soft deleted document. |
Stamp
Stamp documents with creation and update timestamp and user.
Configuration
Stamp has no configuration options. Just use:
$manifest = new Zoop\Shard\Manifest([ ... 'extension_configs' => [ 'extension.stamp' => true ], ... ]);
Create and Update stamps
Timestamps
The stamp extension supports automatic timestamping of create and update events on documents. Use the @Shard\Stamp\CreatedOn
and @Shard\Stamp\UpdatedOn
annotations. Eg:
/** * @ODM\Timestamp * @Shard\Stamp\CreatedOn */ protected $createdOn; /** * @ODM\Timestamp * @Shard\Stamp\UpdatedOn */ protected $updatedOn;
Alternately you can use traits. Eg
use Zoop\Shard\Stamp\DataModel\CreatedOnTrait; use Zoop\Shard\Stamp\DataModel\CreatedOnTrait; //Annotation imports use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Zoop\Shard\Annotation\Annotations as Shard; /** @ODM\Document */ class MyDocument { use CreatedOnTrait; use UpdatedOnTrait; ... }
The values of the fields can be retrieved with:
$myDocument->getCreatedOn(); $myDocument->getUpdatedOn();
User stamps
The stamp extension supports automatic stamping with the active username on document create and update. Use the @Shard\Stamp\CreatedBy
and @Shard\Stamp\UpdatedBy
annotations. This requires a configured user. Eg:
/** * @ODM\String * @Shard\Stamp\CreatedBy */ protected $createdBy; /** * @ODM\String * @Shard\Stamp\UpdatedBy */ protected $updatedBy;
Alternately you can use traits. Eg
use Zoop\Shard\State\DataModel\CreatedByTrait; use Zoop\Shard\State\DataModel\UpdatedByTrait; //Annotation imports use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Zoop\Shard\Annotation\Annotations as Shard; /** @ODM\Document */ class MyDocument { use CreatedByTrait; use UpdatedByTrait; ... }
The values of the fields can be retrieved with:
$myDocument->getCreatedBy(); $myDocument->getUpdatedBy();
Access Conntrol
The stamp extension can hook into the Access Control extension to provide the extra roles of creator
and updater
. Permissions can be allowed or denied if the current active user is the creator or updater. Eg:
$manifest = new Zoop\Shard\Manifest([ ... 'extension_configs' => [ 'extension.accessControl' => true, 'extension.stamp' => true ], ... ]);
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Zoop\Shard\Annotation\Annotations as Shard; /** * @ODM\Document * @Shard\AccessControl({ * @Shard\Permission\Basic(roles="creator", allow="update::*") * ... * }) */ class Simple {...}
State
Add state to documents and build document workflows.
A document has a state, such as 'draft' and can be transitioned to another state, such as 'published'.
Configuration
State has no configuration options. Just use:
$manifest = new Zoop\Shard\Manifest([ ... 'extension_configs' => [ 'extension.state' => true ], ... ]);
Adding state to a Document
To add state, add @Shard\State
to a field. Eg:
/** * @ODM\String * @Shard\State */ protected $state;
For convienence you can use the Zoop\Shard\State\DataModel\StateTrait
to add such a field to a document.
State Access Control
Access Control permissions can be tied to document state. Use @Shard\Permission\State
.
Eg. These permissions allow all roles to read only when a document is in a published state. A writer role is allowed to create, read and update documents in a draft state.
/** * @ODM\Document * @Shard\AccessControl({ * @Shard\Permission\State (roles="*", states="published", allow="read" ), * @Shard\Permission\State (roles="writer", states="draft", allow={"create", "update", "read"}), * }) */ class AccessControlled { ... }
States can be listed as an array, and also support wilds. Eg:
/** * @ODM\Document * @Shard\AccessControl({ * @Shard\Permission\State (roles="*", states="published", allow="read" ), * @Shard\Permission\State (roles="writer", states={"d*", "published"}, allow={"create", "update", "read"}), * }) */ class AccessControlled { ... }
Transition Access Control
Access Control permission can use used to control who can make changes to document state. Use @Shard\Permission\Transition
Eg. These permissions allow a writer to move a document from draft to reivew. A reviewer may move a document from review to draft or review to published. An admin can make any transition.
/** * @ODM\Document * @Shard\AccessControl({ * @Shard\Permission\Transition(roles="writer", allow="draft->review" ), * @Shard\Permission\Transition(roles="reviewer", allow={"review->draft", "review->published"}), * @Shard\Permission\Basic (roles="admin", allow="*" ) * }) */ class AccessControlled { ... }
Transitions can have wilds. (very handy).
/** * @ODM\Document * @Shard\AccessControl({ * @Shard\Permission\Transition(roles="writer", allow="draft->review"), * @Shard\Permission\Transition(roles="reviewer", allow="review->*" ), * @Shard\Permission\Basic (roles="admin", allow="*" ) * }) */ class AccessControlled { ... }
State Filter
The state extension provides a filter that can be used to filter result sets based on document state.
The state filter takes a list of states, and if those states should be included or excluded.
Eg, exclude some states:
$documentManager->getFilterCollection()->enable('state'); $filter = $documentManager->getFilterCollection()->getFilter('state'); $filter->setStates(['inactive']); $filter->excludeStateList();
Eg, include some states:
$documentManager->getFilterCollection()->enable('state'); $filter = $documentManager->getFilterCollection()->getFilter('state'); $filter->setStates(['published', 'draft']); $filter->includeStateList();
Events
State provides the following events which can be subscribed to with the Doctrine EventManager:
| Name | description |
|---|---|
| preTransition | Fires before state transition happens. |
| onTransition | Fires when a transition is happening. That is, after access control checks but before a new document change set is prepared for document persistance. |
| postTransition | Fires after a transition has happened. |
| transitionDenied | Fires if Access Control has denied permission to make a requested transition. |
Validator
Add validation to documents.
Validate fields, and whole documents so only quality data makes it into your database.
The Validator extensions uses the Mystique validator library.
Configuration
State has no configuration options. Just use:
$manifest = new Zoop\Shard\Manifest([ ... 'extension_configs' => [ 'extension.validator' => true ], ... ]);
Adding validation to a Field
To add a validator use annotations in the @Shard\Validator
namespace. Eg:
/** * @ODM\String * @Shard\Validator\Length("min" = 5, "max" = 10) */ protected $myproperty;
To add a multiple validators in a chain, use @Shard\Validator\Chain
. Eg:
/** * @ODM\String * @Shard\Validator\Chain({ * @Shard\Validator\Alpha, * @Shard\Validator\Length("min" = 5, "max" = 10) * }) */ protected $myproperty;
All the validators in the Mystique library are supported with their own annotation.
Custom Validators
To write your own validators, inherit from Zoop\Mystique\Base
and use the @Shard\Validator
annotation.
/** * @ODM\String * @Shard\Validator("class" = "My\Validator\Class", "options" = {"constuctor options array"}) */ protected $myproperty;
Document validators
Sometimes you want a validation rule that interrogates more than one field. To do so, just use the @Shard\Validator
annotation on a document, rather than a field. Eg:
/** * @ODM\Document * @Shard\Validator(class = "Zoop\Shard\Test\Validator\TestAsset\ClassValidator") */ class Simple { ... }
The isValid
method of the validator will be passed the complete document instance to validate.
Document Validator Service
To validate a document before flush, use the documentValidator service. This will validate all fields and any document validators. Eg:
$documentValidator = $manifest->getServiceManager()->get('documentValidator'); $result = $documentValidator->isValid($myDocument);
Events
Validator provides the following events which can be subscribed to with the Doctrine EventManager:
| Name | description |
|---|---|
| invalidUpdate | Fires during flush if and updated document is invalid. |
| invalidCreate | Fires during flush if and updated document is invalid. |
Zone
Add zones to documents.
A zone is a region of relevance. For example, it may be a company department, a geographical area.
A document may be assigned multiple zones.
Configuration
Zone has no configuration options. Just use:
$manifest = new Zoop\Shard\Manifest([ ... 'extension_configs' => [ 'extension.zone' => true ], ... ]);
Adding zones to a Document
To add zones, add @Shard\Zones
to a field. Eg:
/** * @ODM\Collection * @Shard\Zones */ protected $zones;
For convienence you can use the Zoop\Shard\Zone\DataModel\ZoneTrait
to add such a field to a document.
Zone Filter
The zone extension provides a filter that can be used to filter result sets based on document zones.
The zone filter takes a list of zones, and if those zones should be included or excluded.
Eg, exclude some zones:
$documentManager->getFilterCollection()->enable('zone'); $filter = $documentManager->getFilterCollection()->getFilter('zone'); $filter->setStates(['business-support']); $filter->excludeZoneList();
Eg, include some states:
$documentManager->getFilterCollection()->enable('zone'); $filter = $documentManager->getFilterCollection()->getFilter('zone'); $filter->setStates(['accounts', 'hr']); $filter->includeZoneList();


Please fill in the form below
Which part of the stack do you prefer?
Select an option
Frontend
Backend
Both
How many programming languages do you have experience with?
0
1-2
3-4
5-6
7+
How long have you been programming for?
Which SQL database do you have most experience with?
PostgreSQL
MySQL
Oracle
SQL Server
Submit


(Deprecated API)
(Deprecated API)
(Deprecated API)
Same great maps plus a SLA, support, and control over ads
Note: The Google Maps Javascript API Version 3 documented within these pages is now the official Javascript API. Version 2 of this API has been officially deprecated as per our deprecation policy. We encourage you to migrate your code to this newly updated and enhanced version!
The maps on Google Maps contain UI elements for allowing user interaction through the map. These elements are known as controls and you can include variations of these controls in your Google Maps API application. Alternatively, you can do nothing and let the Google Maps API handle all control behavior.
The Maps API comes with a handful of built-in controls you can use in your maps:
ROADMAP
and SATELLITE
). This control
appears by default in the top right corner of the map.You don't access or modify these map controls directly. Instead, you
modify the map's MapOptions
fields which affect the visibility
and presentation of controls. You can adjust control presentation upon
instantiating your map (with appropriate MapOptions
) or modify a
map dynamically by calling setOptions()
to change the map's
options.
Not all of these controls are enabled by default. To learn about default UI behavior (and how to modify such behavior), see The Default UI below.
Rather than specifying and setting up individual controls, you may simply wish to specify that your map exhibit the look and feel of the Google Maps interface, (including any new features or controls that get added in the future). To get this behavior, you need do nothing. Your map will show up with default controls.
The Maps API provides the following default controls:
| Control | Large Screens | Small Screens | iPhone | Android |
|---|---|---|---|---|
| Navigation | Large Pan/Zoom for sizes larger than 400x350px | Small Mini-Zoom for sizes smaller than 400x350px | Not present | "Android" control |
| MapType | Horizontal Bar for screens larger than 320px wide | Dropdown for screens smaller than 320px wide | Same as Large/Small Screens | Same as Large/Small Screens |
| Scale | Not present | Not present | Not present | Not present |
Additionally, keyboard handling is on by default on all devices.
You may instead wish to turn off the API's default UI settings. To do so,
set the Map
's disableDefaultUI
property (within the
Map options
object) to true
. This property
disables any automatic UI behavior from the Google Maps API.
The following code disables the default UI entirely:
function initialize() { var myOptions = { zoom: 4, center: new google.maps.LatLng(-33, 151), disableDefaultUI: true, mapTypeId: google.maps.MapTypeId.ROADMAP } var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions); }
View example (control-disableUI.html)
You may wish to tailor your interface by removing, adding, or modifying UI behavior or controls and ensure that future updates don't alter this behavior. If you wish to only add or modify existing behavior, you need to ensure that the control is explicitly added to your application.
Some controls appear on the map by default while others will not appear
unless you specifically request them. Adding or removing controls from the map
is specified in the following Map options
object's fields,
which you set to true
to make them visible or set to
false
to hide them:
{ navigationControl: boolean, mapTypeControl: boolean, scaleControl: boolean }
Note that the Maps API V3 does not currently allow you to dynamically add
or remove controls. These must be set upon creation of the map through a
Map options
object.
The following example sets the map to hide the navigation control and display the scale control. Note that we do not explicitly disable the default UI, so these modifications are additive to the default UI behavior.
function initialize() { var myOptions = { zoom: 4, center: new google.maps.LatLng(-33, 151), navigationControl: false, scaleControl: true, mapTypeId: google.maps.MapTypeId.ROADMAP } var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions); }
View example (control-simple.html)
Several controls are configurable, allowing you to alter their behavior or change their appearance. The Navigation control, for example, may display as either a large control with a full zoom control and panning controls as shown on Google Maps, or as a smaller, mini-zoom control for smaller devices.
These controls are modified by altering appropriate control options
fields within the MapOptions
object upon creation of the map. For
example, options for altering the Navigation control are
indicated in the navigationControlOptions
field.
The Navigation control may appear in one of the following
style
options:
google.maps.NavigationControlStyle.SMALL
displays
a mini-zoom control, consisting of only + and - buttons.
This style is appropriate for mobile devices.google.maps.NavigationControlStyle.ZOOM_PAN
displays the standard zoom slider control with a panning control,
as on Google Maps.google.maps.NavigationControlStyle.ANDROID
displays
the small zoom control as used on the native Maps application on
Android devices.google.maps.NavigationControlStyle.DEFAULT
picks
an appropriate navigation control based on the map's size and the
device on which the map is running.The MapType control may appear in one of the following
style
options:
google.maps.MapTypeControlStyle.HORIZONTAL_BAR
displays the array of controls as buttons in a horizontal bar as
is shown on Google Maps.google.maps.MapTypeControlStyle.DROPDOWN_MENU
displays a single button control allowing you to select the map
type via a dropdown menu.google.maps.MapTypeControlStyle.DEFAULT
displays
the "default" behavior, which depends on screen size and may
change in future versions of the APINote that if you do modify any control options, you should
explicitly enable the control as well by setting the appropriate
MapOptions
value to true
. For example,
to set a Navigation control to exhibit the SMALL
style, use the following code within the MapOptions
object:
... navigationControl: true, navigationControlOptions: { style: google.maps.NavigationControlStyle.SMALL } ...
The following example sets a drop-down MapType control and specifies that the Navigation control use a small mini-zoom layout:
function initialize() { var myOptions = { zoom: 4, center: new google.maps.LatLng(-33, 151), mapTypeControl: true, mapTypeControlOptions: { style: google.maps.MapTypeControlStyle.DROPDOWN_MENU }, navigationControl: true, navigationControlOptions: { style: google.maps.NavigationControlStyle.SMALL }, mapTypeId: google.maps.MapTypeId.ROADMAP } var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions); }
View example (control-options.html)
Controls are typically configured upon creation of the map. However,
you may alter the presentation of controls dynamically by
calling the Map
's setOptions()
method,
passing it new control options.
You specify a control's presentation when you create your map
through fields within the map's MapOptions
object. These
fields are denoted below:
mapTypeControl
enables/disables the Map Type control
that lets the user toggle between map types (such as Map and Satellite).
By default, this control is visible and appears in the top right
corner of the map. The mapTypeControlOptions
field
additionally specifies the MapTypeControlOptions
to
use for this control.navigationControl
enables/disables the Navigation
control that provides a pan/zoom control. By default, this control
is visible and appears in the top left corner of the map. The
navigationControlOptions
field additionally specifies the
NavigationControlOptions
to use for this control.scaleControl
enables/disables the Scale control
that provides a simple map scale. By default, this control is
not visible. When enabled, it appears in the bottom left corner of
the map. The scaleControlOptions
additionally specifies the
ScaleControlOptions
to use for this control.Note that you may specify options for controls you initially disable.
Each of these control options contains a position
property
(of type ControlPosition
) which indicates where on the map to
place the control. Positioning of these controls is not absolute; instead, the
API will layout the controls intelligently by "flowing" them around existing
map elements, or other controls, within given constraints (such as the map
size). Note: no guarantees can be made that
controls may not overlap given complicated layouts, though the API will
attempt to arrange them intelligently.
The following control positions are supported:
TOP_CENTER
indicates that the control should be placed
along the top center of the map.TOP_LEFT
indicates that the control should be placed along
the top left of the map, with any sub-elements of the control "flowing"
towards the top center.TOP_RIGHT
indicates that the control should be placed along
the top right of the map, with any sub-elements of the control "flowing"
towards the top center.LEFT_TOP
indicates that the control should be placed along
the top left of the map, but below any TOP_LEFT
elements.RIGHT_TOP
indicates that the control should be placed along
the top right of the map, but below any TOP_RIGHT
elements.LEFT_CENTER
indicates that the control should be placed along
the left side of the map, centered between the TOP_LEFT
and
BOTTOM_LEFT
positions.RIGHT_CENTER
indicates that the control should be placed
along the right side of the map, centered between the TOP_RIGHT
and
BOTTOM_RIGHT
positions.LEFT_BOTTOM
indicates that the control should be placed along
the bottom left of the map, but above any BOTTOM_LEFT
elements.RIGHT_BOTTOM
indicates that the control should be placed along
the bottom right of the map, but above any BOTTOM_RIGHT
elements.BOTTOM_CENTER
indicates that the control should be placed
along the bottom center of the map.BOTTOM_LEFT
indicates that the control should be placed
along the bottom left of the map, with any sub-elements of the control
"flowing" towards the bottom center.BOTTOM_RIGHT
indicates that the control should be placed
along the bottom right of the map, with any sub-elements of the control
"flowing" towards the bottom center.Note that these positions may coincide with positions of UI elements whose placements you may not modify (such as copyrights and the Google logo). In those cases, the controls will "flow" according to the logic noted for each position and appear as close as possible to their indicated position.
The following example shows a simple map with all controls enabled, in different positions.
function initialize() { var myOptions = { zoom: 12, center: new google.maps.LatLng(-28.643387, 153.612224), mapTypeId: google.maps.MapTypeId.ROADMAP, mapTypeControl: true, mapTypeControlOptions: { style: google.maps.MapTypeControlStyle.HORIZONTAL_BAR, position: google.maps.ControlPosition.BOTTOM }, navigationControl: true, navigationControlOptions: { style: google.maps.NavigationControlStyle.ZOOM_PAN, position: google.maps.ControlPosition.TOP_RIGHT }, scaleControl: true, scaleControlOptions: { position: google.maps.ControlPosition.TOP_LEFT } } var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions); }
View example (control-positioning.html)
As well as modifying the style and position of existing API controls, you
can create your own controls to handle interaction with the user. Controls are
stationary widgets which float on top of a map at absolute positions, as
opposed to overlays, which move with the underlying map. More
fundamentally, a control is simply a

element which
has an absolute position on the map, displays some UI to the user, and handles
interaction with either the user or the map, usually through an event
handler.
To create your own custom control, few "rules" are necessary. However, the following guidelines can act as best practices:
'click'
events).

element to hold the control and add
this element to the Map
's controls
property.Each of these concerns is discussed below.
 Generally, we recommend that you
place all of your control presentation within a single

element so that you can manipulate your control as
one unit. We will use this design pattern in the samples shown below.
Designing attractive controls requires some knowledge of CSS and DOM
structure. The following code shows how a simple control is created from a
containing

, a

to hold the
button outline, and another

to hold the button
interior.
// Create a div to hold the control. var controlDiv = document.createElement('DIV'); // Set CSS styles for the DIV containing the control // Setting padding to 5 px will offset the control // from the edge of the map controlDiv.style.padding = '5px'; // Set CSS for the control border var controlUI = document.createElement('DIV'); controlUI.style.backgroundColor = 'white'; controlUI.style.borderStyle = 'solid'; controlUI.style.borderWidth = '2px'; controlUI.style.cursor = 'pointer'; controlUI.style.textAlign = 'center'; controlUI.title = 'Click to set the map to Home'; controlDiv.appendChild(controlUI); // Set CSS for the control interior var controlText = document.createElement('DIV'); controlText.style.fontFamily = 'Arial,sans-serif'; controlText.style.fontSize = '12px'; controlText.style.paddingLeft = '4px'; controlText.style.paddingRight = '4px'; controlText.innerHTML = 'Home'; controlUI.appendChild(controlText);
For a control to be useful, it must actually do something. What the control
does is up to you. The control may respond to user input, or it may respond to
changes in the Map
's state.
For responding to user input, the Maps API provides a cross-browser event
handling method addDomListener()
which handles most of the
browser's supported DOM
events. The following code snippet adds a listener for the browser's
'click'
event. Note that this event is received from the DOM, not
from the map.
// Setup the click event listener: simply set the map to center on Chicago var chicago = new google.maps.LatLng(41.850033, -87.6500523); google.maps.event.addDomListener(outer, 'click', function() { map.setCenter(chicago) });
Custom controls are positioned on the map by placing them at appropriate
positions within the Map
object's controls
property.
This property contains an array of google.maps.ControlPosition
s.
You add a custom control to the map by adding the Node
(typically
the

) to an appropriate ControlPosition
.
(For information on these positions, see Control
Positioning above.)
Each ControlPosition
stores an MVCArray
of the
controls displayed in that position. As a result, when controls are added or
removed from the position, the API will update the controls accordingly.
The API places controls at each position by the order of an
index
property; controls with a lower index are placed first. For
example, two custom controls at position BOTTOM_RIGHT
will be
laid out according to this index order, with lower index values taking
precedence. By default, all custom controls are placed after placing
any API default controls. You can override this behavior by setting a
control's index
property to be a negative value. Note that you
will normally only need to set an index value if you wish to place your
control "before" a default API control in the same position.
The following code creates a new custom control (its constructor is not
shown) and adds it to the map in the TOP_RIGHT
position.
var map = new google.maps.Map(document.getElementById('map_canvas'), mapOptions); // Construct your control in whatever manner is appropriate. // Generally, your constructor will want access to the // DIV on which you'll attach the control UI to the Map. var controlDiv = document.createElement('DIV'); var myControl = new MyControl(controlDiv); // We don't really need to set an index value here, but // this would be how you do it. Note that we set this // value as a property of the DIV itself. controlDiv.index = 1; // Add the control to the map at a designated control position // by pushing it on the position's array. This code will // implicitly add the control to the DOM, through the Map // object. You should not attach the control manually. map.controls[google.maps.ControlPosition.TOP_RIGHT].push(controlDiv);
The following control is simple (though not particularly useful) and
combines the patterns shown above. This control responds to DOM
'click'
events by centering the map at a certain default
location:
var map; var chicago = new google.maps.LatLng(41.850033, -87.6500523); /** * The HomeControl adds a control to the map that simply * returns the user to Chicago. This constructor takes * the control DIV as an argument. */ function HomeControl(controlDiv, map) { // Set CSS styles for the DIV containing the control // Setting padding to 5 px will offset the control // from the edge of the map controlDiv.style.padding = '5px'; // Set CSS for the control border var controlUI = document.createElement('DIV'); controlUI.style.backgroundColor = 'white'; controlUI.style.borderStyle = 'solid'; controlUI.style.borderWidth = '2px'; controlUI.style.cursor = 'pointer'; controlUI.style.textAlign = 'center'; controlUI.title = 'Click to set the map to Home'; controlDiv.appendChild(controlUI); // Set CSS for the control interior var controlText = document.createElement('DIV'); controlText.style.fontFamily = 'Arial,sans-serif'; controlText.style.fontSize = '12px'; controlText.style.paddingLeft = '4px'; controlText.style.paddingRight = '4px'; controlText.innerHTML = 'Home'; controlUI.appendChild(controlText); // Setup the click event listeners: simply set the map to Chicago google.maps.event.addDomListener(controlUI, 'click', function() { map.setCenter(chicago) }); } function initialize() { var mapDiv = document.getElementById('map_canvas'); var myOptions = { zoom: 12, center: chicago, mapTypeId: google.maps.MapTypeId.ROADMAP } map = new google.maps.Map(mapDiv, myOptions); // Create the DIV to hold the control and call the HomeControl() constructor // passing in this DIV. var homeControlDiv = document.createElement('DIV'); var homeControl = new HomeControl(homeControlDiv, map); homeControlDiv.index = 1; map.controls[google.maps.ControlPosition.TOP_RIGHT].push(homeControlDiv); }
View example (control-custom.html)
Controls may also store state. The following example is similar to that
shown before, but the control contains an additional "Set Home" button which
sets the control to exhibit a new home location. We do so by creating a
home_
property within the control to store this state and provide
getters and setters for that state.
var map; var chicago = new google.maps.LatLng(41.850033, -87.6500523); /** * The HomeControl adds a control to the map that * returns the user to the control's defined home. */ // Define a property to hold the Home state HomeControl.prototype.home_ = null; // Define setters and getters for this property HomeControl.prototype.getHome = function() { return this.home_; } HomeControl.prototype.setHome = function(home) { this.home_ = home; } function HomeControl(map, div, home) { // Get the control DIV. We'll attach our control UI to this DIV. var controlDiv = div; // We set up a variable for the 'this' keyword since we're adding event // listeners later and 'this' will be out of scope. var control = this; // Set the home property upon construction control.home_ = home; // Set CSS styles for the DIV containing the control. Setting padding to // 5 px will offset the control from the edge of the map controlDiv.style.padding = '5px'; // Set CSS for the control border var goHomeUI = document.createElement('DIV'); goHomeUI.title = 'Click to set the map to Home'; controlDiv.appendChild(goHomeUI); // Set CSS for the control interior var goHomeText = document.createElement('DIV'); goHomeText.innerHTML = 'Home'; goHomeUI.appendChild(goHomeText); // Set CSS for the setHome control border var setHomeUI = document.createElement('DIV'); setHomeUI.title = 'Click to set Home to the current center'; controlDiv.appendChild(setHomeUI); // Set CSS for the control interior var setHomeText = document.createElement('DIV'); setHomeText.innerHTML = 'Set Home'; setHomeUI.appendChild(setHomeText); // Setup the click event listener for Home: // simply set the map to the control's current home property. google.maps.event.addDomListener(goHomeUI, 'click', function() { var currentHome = control.getHome(); map.setCenter(currentHome); }); // Setup the click event listener for Set Home: // Set the control's home to the current Map center. google.maps.event.addDomListener(setHomeUI, 'click', function() { var newHome = map.getCenter(); control.setHome(newHome); }); } function initialize() { var mapDiv = document.getElementById('map_canvas'); var myOptions = { zoom: 12, center: chicago, mapTypeId: google.maps.MapTypeId.ROADMAP } map = new google.maps.Map(mapDiv, myOptions); // Create the DIV to hold the control and call the HomeControl() // constructor passing in this DIV. var homeControlDiv = document.createElement('DIV'); var homeControl = new HomeControl(map, homeControlDiv, chicago); homeControlDiv.index = 1; map.controls[google.maps.ControlPosition.TOP_RIGHT].push(homeControlDiv); }


|
|
| Wedding Story : Damien's Story |
| Damien's life has always seemed to be in flux. He started changing schedules right off the bat when he decided it was time to be born a couple of weeks early... even though his father's car was in the shop in preparation for his coming... later. As Damien grew up in Cincinnati, he got used to this mutability, switching from Mercy Montessori School (up through grade 4) to Nativity (grades 5 through 8). |
| < 1 2 3 4 5 > |
|


Hooks are useful for defining additional checks that should be performed prior to and during training and prediction. For example, one might want to issue a warning if the user is predicting on rows that were used for training, or a sanity check might be present prior to training to ensure a dependent variable is present.
Add a hook to a tundraContainer.
run_hooks(hook_name) add_hook(hook_name, hook_function)
| hook_name | character. The hook to run. Must be one of the available hooks. |
|---|---|
| hook_function | function. The hook to execute. It will be provided
the |
The following hooks are available.
train_pre_mungeThis hook runs during a call to the
container's train
method, just prior to invoking the
munge_procedure
to clean up the dataset. It could be
useful for defining pre-conditions on the dataset to ensure
it can be munged successfully.
train_post_mungeThis hook runs during a call to the
container's train
method, just after invoking the
munge_procedure
to clean up the dataset. It could be
useful for defining post-conditions on the dataset to ensure
it was munged successfully.
train_finalizeThis hook runs just after the train
method calls the train_function
. It could be used to
verify presence or validate properties of the trained model.
predict_pre_mungeThis hook runs during a call to the
container's predict
method, just prior to invoking the
munge_procedure
to clean up the dataset. It could be
useful for defining pre-conditions on the dataset to ensure
it can be munged successfully.
predict_post_mungeThis hook runs during a call to the
container's predict
method, just after invoking the
munge_procedure
to clean up the dataset. It could be
useful for defining post-conditions on the dataset to ensure
it was munged successfully.
Each hook will be provided the tundraContainer
as input
(unless it has no arguments, in which case it will simply be called).


{% extends 'base.html' %} {% block body %} Home Actors Directors Genres Keywords Movies(current) Screenwriters IMDB Score Prediction Login Register
Total Number of Movies: {{movie_dict['total_results']}}
The movie of name "{{ movie_name }}" was not found in our records.


Now that we've seen some of what we can do with containers, we're going to turn our
attention back to string
s. Until now, we've done only a few things with string
s:
We've created them, read them, concatenated them, written them, and looked at their
size. In each of these uses, we have dealt with the string
as a single entity. Often, this
kind of abstract usage is what we want: We want to ignore the detailed contents of a
string
. Sometimes, though, we need to look at the specific characters in a string
.
As it turns out, we can think of a string
as a special kind of container: It contains
only characters, and it supports some, but not all, of the container operations. The operations
that it does support include indexing, and the string
type provides an iterator that
is similar to a vector
iterator. Thus, many of the techniques that we can apply to
vector
s apply also to string
s.
For example, we might want to break a line of input into words, separated from each
other by whitespace (space, tab, backspace, or the end of the line). If we can read the
input directly, we can get the words from the input trivially. After all, that's exactly how
the string
input operator executes: It reads characters up to the whitespace character.
However, there are times when we want to read an entire line of input and examine the words within that line. We'll see examples in §7.3/126 and §7.4.2/131.
Because such an operation might be generally useful, we'll write a function to do it.
The function will take a string
and return a vector<string>
, which will contain an
entry for each whitespace-separated word in that string
. In order to understand this
function, you need to know that string
s support indexing much the same way as
vector
s do. So, for example, if s
is a string
that contains at least one character, the
first character of s
is s[0]
, and the last character of s
is s[s.size() - 1]
.
Our function will define two indices, i
and j
, that will delimit each word in turn. The
idea is that we will locate a word by computing values for i
and j
such that the word will
be the characters in the range [i, j)
. For example,
Once we have these indices, we'll use the characters that they delimit to create a new
string
, which we will copy into our vector
. When we are done, we will return the
vector
to our caller:
vector<string> split(const string& s) { vector<string> ret; typedef string::size_type string_size; string_size i = 0; // invariant: we have processed characters [original value of i, i) while (i != s.size()) { // ignore leading blanks // invariant: characters in range [original i, current i) are all spaces while (i != s.size() && isspace(s[i])) ++i; // find end of next word string_size j = i; // invariant: none of the characters in range [original j, current j)is a space while (j != s.size() && !isspace(s[j])) j++; // if we found some nonwhitespace characters if (i != j) { // copy from s starting at i and taking j - i chars ret.push_back(s.substr(i, j - i)); i = j; } } return ret; }
In addition to the system headers that we have already encountered, this code needs the
<cctype>
header, which defines isspace
. More generally, this header defines useful
functions for processing individual characters. The c
at the beginning of cctype
is a
reminder that the ctype
facility is part of C++'s inheritance from C.
The split
function has a single parameter, which is a reference to a const string
that we'll name s
. Because we will be copying words from s
, split
does not need to
change the string
. As in §4.1.2/54, we can pass a const
reference to avoid the cost of
copying the string
, while still ensuring that split
will not change its argument.
We start off by defining ret
, which will hold the words from the input string
. The
next two statements define and initialize our first index, i
. As we saw in §2.4/22,
string::size_type
is the name for the appropriate type to index a string
. Because
we need to use this type more than once, we start by defining a shorter synonym for this
type, as we did in §3.2.2/43, to simplify the subsequent declarations. We will use i
as the
index that finds the start of each word, advancing i
through the input string
one word at a time.
The test in the outermost while
ensures that once we've processed the last word in
the input, we'll stop.
Inside the while
, we start by positioning our two indices. First, we find the first non-space
character in s
that is at or after the position currently indicated by i
. Because there
might be multiple whitespace characters in the input, we increment i
until it denotes a
character that is not whitespace.
There is a lot going on in this statement:
while (i != s.size() && isspace(s[i])) ++i;
The isspace
function is a predicate that takes a char
and returns a value that indicates
whether that char
is whitespace. The &&
operator tests whether both its operands are
true
, failing if either of them is false
. In this expression, the operation will succeed if i
is not equal to the size of s
(meaning that we have not reached the end of the string
),
and s[i]
is a whitespace character. In that case, we will increment i
and check again.
As we described in §<IP_ADDRESS>/26, the logical &&
operation uses a short-circuit strategy for
evaluating its operands. Unlike our earlier examples, this one relies on the short-circuit
property of &&
. The binary logical operations (operators &&
and ||
) execute by testing their
left-hand operands first. If that test suffices to determine the overall result, then the
right-hand operand is not evaluated. In the case of the &&
, the second condition is evaluated
if and only if the first condition is true
. Thus, the condition in the while
executes
by first checking whether i != s.size()
. Only if this test succeeds does it use i
to look
at a character in s
. Of course, if i
is equal to s.size()
, then there are no more characters
left to examine, and so we drop out of the loop.
Once we fall out of this while
, we know either that i
denotes a character that is not
whitespace, or that we've run out of input without finding such a character.
Assuming that i
is still a valid index, the next while
will find the space that terminates
the current word in s
. We start by creating our other index, j
, and initializing it to
the value of i
. The next while
,
while (j != s.size() && !isspace(s[j])) ++j;
executes similarly to the previous one, but this time the while
stops when it encounters a
whitespace character. As before, we start by ensuring that j
is still in range. If so, we
again call isspace
on the character indexed by j
. This time, we negate the return from
isspace
using the logical negation operator, !
. In other words, we want the condition to
be true if isspace(s[j])
is not true
.
Having completed the two inner while
loops, we know that we have either found
another word or run out of input while looking for a word. If we have run out of input,
then both i
and j
will be equal to s.size()
. Otherwise, we have found a word, which
we must push onto ret
:
// if we found some nonwhitespace characters if (i != j) { // copy from s starting at i and taking j - i chars ret.push_back(s.substr(i, j - i)); i = j; }
The call to push_back
uses a member of the string
class, named substr
, that we have
not previously seen. It takes an index and a length, and creates a new string
that contains
a copy of characters from the initial string
, starting at the index given by the first
argument, and copying as many characters as indicated by its second argument. The substring
that we extract starts at i
, which is the first character in the word that we just
found. We copy characters from s
starting with the one indexed by i
, and continuing
until we have copied the characters in the (half-open) range [i, j)
. Remembering from
§2.6/31 that the number of elements in a half-open range is the difference between the
bounds, we see that we will copy exactly j - i
characters.


BlockChain: Blockchain is an advanced way of logging and protecting data and changes to a decentralised database that makes it impossible to change or hack. It's the technology that underpins digital currencies, such as Bitcoin, helping to protect against double-spending and hyperinflation in banking, and helping achieve automated supply chain management in manufacturing.
Autonomous Things (Robots):Autonomous robots can act on their own, independent of any controller. The basic idea is to program the robot to respond a certain way to outside stimuli.
Immersive Experience:Virtual reality is a perception of being physically present in a non-physical world. The perception is created by surrounding the user of the VR system in images, sound or other stimuli that provide an engrossing total environment.


Thanks for coming to our conference. It wouldn't have been the same without you!
We hope it's ok for us to notify your once in a while through your mobile:<PHONE_NUMBER>
Political activism is at the heart of any democracy and your voice needs to be heard. Please consider reaching out to your representatives:
| Legislators | Website |
|---|---|
| Kamala D. Harris | https://www.harris.senate.gov |
| Dianne Feinstein | https://www.feinstein.senate.gov/ |