text:
package typed

import (
	"encoding/binary"
	"errors"
	"io"
)

var (
	// ErrEOF is returned when trying to read past end of buffer
	ErrEOF = errors.New("buffer is too small")

	// ErrBufferFull is returned when trying to write past end of buffer
	ErrBufferFull = errors.New("no more room in buffer")

	// errStringTooLong is returned when writing a string with length larger
	// than the allows length limit. Intentionally not exported, in case we
	// want to add more context in future.
	errStringTooLong = errors.New("string is too long")
)

// A ReadBuffer is a wrapper around an underlying []byte with methods to read from
// that buffer in big-endian format.
type ReadBuffer struct {
	initialLength int
	remaining     []byte
	err           error
}

// NewReadBuffer returns a ReadBuffer wrapping a byte slice
func NewReadBuffer(buffer []byte) *ReadBuffer {
	return &ReadBuffer{initialLength: len(buffer), remaining: buffer}
}

// ReadSingleByte reads the next byte from the buffer
func (r *ReadBuffer) ReadSingleByte() byte {
	b, _ := r.ReadByte()
	return b
}

// ReadByte returns the next byte from the buffer.
//
// This method implements the ByteReader interface.
func (r *ReadBuffer) ReadByte() (byte, error) {
	if r.err != nil {
		return 0, r.err
	}

	if len(r.remaining) < 1 {
		r.err = ErrEOF
		return 0, r.err
	}

	b := r.remaining[0]
	r.remaining = r.remaining[1:]
	return b, nil
}

// ReadBytes returns the next n bytes from the buffer
func (r *ReadBuffer) ReadBytes(n int) []byte {
	if r.err != nil {
		return nil
	}

	if len(r.remaining) < n {
		r.err = ErrEOF
		return nil
	}

	b := r.remaining[0:n]
	r.remaining = r.remaining[n:]
	return b
}

// SkipBytes skips the next n bytes from the buffer
func (r *ReadBuffer) SkipBytes(n int) {
	if r.err != nil {
		return
	}

	if len(r.remaining) < n {
		r.err = ErrEOF
		return
	}

	r.remaining = r.remaining[n:]
}

// ReadString returns a string of size n from the buffer
func (r *ReadBuffer) ReadString(n int) string {
	if b := r.ReadBytes(n); b != nil {
		// TODO(mmihic): This creates a copy, which sucks
		return string(b)
	}

	return ""
}

// ReadUint16 returns the next value in the buffer as a uint16
func (r *ReadBuffer) ReadUint16() uint16 {
	if b := r.ReadBytes(2); b != nil {
		return binary.BigEndian.Uint16(b)
	}

	return 0
}

// ReadUint32 returns the next value in the buffer as a uint32
func (r *ReadBuffer) ReadUint32() uint32 {
	if b := r.ReadBytes(4); b != nil {
		return binary.BigEndian.Uint32(b)
	}

	return 0
}

// ReadUint64 returns the next value in the buffer as a uint64
func (r *ReadBuffer) ReadUint64() uint64 {
	if b := r.ReadBytes(8); b != nil {
		return binary.BigEndian.Uint64(b)
	}

	return 0
}

// ReadUvarint reads an unsigned varint from the buffer.
func (r *ReadBuffer) ReadUvarint() uint64 {
	v, _ := binary.ReadUvarint(r)
	return v
}

// ReadLen8String reads an 8-bit length preceded string value
func (r *ReadBuffer) ReadLen8String() string {
	n := r.ReadSingleByte()
	return r.ReadString(int(n))
}

// ReadLen16String reads a 16-bit length preceded string value
func (r *ReadBuffer) ReadLen16String() string {
	n := r.ReadUint16()
	return r.ReadString(int(n))
}

// Remaining returns the unconsumed bytes.
func (r *ReadBuffer) Remaining() []byte {
	return r.remaining
}

// BytesRemaining returns the length of Remaining.
func (r *ReadBuffer) BytesRemaining() int {
	return len(r.Remaining())
}

// BytesRead returns the number of bytes consumed
func (r *ReadBuffer) BytesRead() int {
	return r.initialLength - len(r.remaining)
}

// Wrap initializes the buffer to read from the given byte slice
func (r *ReadBuffer) Wrap(b []byte) {
	r.initialLength = len(b)
	r.remaining = b
	r.err = nil
}

// Err returns the error in the ReadBuffer
func (r *ReadBuffer) Err() error { return r.err }

// A WriteBuffer is a wrapper around an underlying []byte with methods to write to
// that buffer in big-endian format.  The buffer is of fixed size, and does not grow.
type WriteBuffer struct {
	buffer    []byte
	remaining []byte
	err       error
}

// NewWriteBuffer creates a WriteBuffer wrapping the given slice
func NewWriteBuffer(buffer []byte) *WriteBuffer {
	return &WriteBuffer{buffer: buffer, remaining: buffer}
}

// NewWriteBufferWithSize create a new WriteBuffer using an internal buffer of the given size
func NewWriteBufferWithSize(size int) *WriteBuffer {
	return NewWriteBuffer(make([]byte, size))
}

// WriteSingleByte writes a single byte to the buffer
func (w *WriteBuffer) WriteSingleByte(n byte) {
	if w.err != nil {
		return
	}

	if len(w.remaining) == 0 {
		w.setErr(ErrBufferFull)
		return
	}

	w.remaining[0] = n
	w.remaining = w.remaining[1:]
}

// WriteBytes writes a slice of bytes to the buffer
func (w *WriteBuffer) WriteBytes(in []byte) {
	if b := w.reserve(len(in)); b != nil {
		copy(b, in)
	}
}

// WriteUint16 writes a big endian encoded uint16 value to the buffer
func (w *WriteBuffer) WriteUint16(n uint16) {
	if b := w.reserve(2); b != nil {
		binary.BigEndian.PutUint16(b, n)
	}
}

// WriteUint32 writes a big endian uint32 value to the buffer
func (w *WriteBuffer) WriteUint32(n uint32) {
	if b := w.reserve(4); b != nil {
		binary.BigEndian.PutUint32(b, n)
	}
}

// WriteUint64 writes a big endian uint64 to the buffer
func (w *WriteBuffer) WriteUint64(n uint64) {
	if b := w.reserve(8); b != nil {
		binary.BigEndian.PutUint64(b, n)
	}
}

// WriteUvarint writes an unsigned varint to the buffer
func (w *WriteBuffer) WriteUvarint(n uint64) {
	// A uvarint could be up to 10 bytes long.
	buf := make([]byte, 10)
	varBytes := binary.PutUvarint(buf, n)
	if b := w.reserve(varBytes); b != nil {
		copy(b, buf[0:varBytes])
	}
}

// WriteString writes a string to the buffer
func (w *WriteBuffer) WriteString(s string) {
	// NB(mmihic): Don't just call WriteBytes; that will make a double copy
	// of the string due to the cast
	if b := w.reserve(len(s)); b != nil {
		copy(b, s)
	}
}

// WriteLen8String writes an 8-bit length preceded string
func (w *WriteBuffer) WriteLen8String(s string) {
	if int(byte(len(s))) != len(s) {
		w.setErr(errStringTooLong)
	}

	w.WriteSingleByte(byte(len(s)))
	w.WriteString(s)
}

// WriteLen16String writes a 16-bit length preceded string
func (w *WriteBuffer) WriteLen16String(s string) {
	if int(uint16(len(s))) != len(s) {
		w.setErr(errStringTooLong)
	}

	w.WriteUint16(uint16(len(s)))
	w.WriteString(s)
}

// DeferByte reserves space in the buffer for a single byte, and returns a
// reference that can be used to update that byte later
func (w *WriteBuffer) DeferByte() ByteRef {
	if len(w.remaining) == 0 {
		w.setErr(ErrBufferFull)
		return ByteRef(nil)
	}

	// Always zero out references, since the caller expects the default to be 0.
	w.remaining[0] = 0
	bufRef := ByteRef(w.remaining[0:])
	w.remaining = w.remaining[1:]
	return bufRef
}

// DeferUint16 reserves space in the buffer for a uint16, and returns a
// reference that can be used to update that uint16
func (w *WriteBuffer) DeferUint16() Uint16Ref {
	return Uint16Ref(w.deferred(2))
}

// DeferUint32 reserves space in the buffer for a uint32, and returns a
// reference that can be used to update that uint32
func (w *WriteBuffer) DeferUint32() Uint32Ref {
	return Uint32Ref(w.deferred(4))
}

// DeferUint64 reserves space in the buffer for a uint64, and returns a
// reference that can be used to update that uint64
func (w *WriteBuffer) DeferUint64() Uint64Ref {
	return Uint64Ref(w.deferred(8))
}

// DeferBytes reserves space in the buffer for a fixed sequence of bytes, and
// returns a reference that can be used to update those bytes
func (w *WriteBuffer) DeferBytes(n int) BytesRef {
	return BytesRef(w.deferred(n))
}

func (w *WriteBuffer) deferred(n int) []byte {
	bs := w.reserve(n)
	for i := range bs {
		bs[i] = 0
	}
	return bs
}

func (w *WriteBuffer) reserve(n int) []byte {
	if w.err != nil {
		return nil
	}

	if len(w.remaining) < n {
		w.setErr(ErrBufferFull)
		return nil
	}

	b := w.remaining[0:n]
	w.remaining = w.remaining[n:]
	return b
}

// BytesRemaining returns the number of available bytes remaining in the bufffer
func (w *WriteBuffer) BytesRemaining() int {
	return len(w.remaining)
}

// FlushTo flushes the written buffer to the given writer.
func (w *WriteBuffer) FlushTo(iow io.Writer) (int, error) {
	dirty := w.buffer[0:w.BytesWritten()]
	return iow.Write(dirty)
}

// BytesWritten returns the number of bytes that have been written to the buffer
func (w *WriteBuffer) BytesWritten() int { return len(w.buffer) - len(w.remaining) }

// Reset resets the buffer to an empty state, ready for writing
func (w *WriteBuffer) Reset() {
	w.remaining = w.buffer
	w.err = nil
}

func (w *WriteBuffer) setErr(err error) {
	// Only store the first error
	if w.err != nil {
		return
	}

	w.err = err
}

// Err returns the current error in the buffer
func (w *WriteBuffer) Err() error { return w.err }

// Wrap initializes the buffer to wrap the given byte slice
func (w *WriteBuffer) Wrap(b []byte) {
	w.buffer = b
	w.remaining = b
}

// A ByteRef is a reference to a byte in a bufffer
type ByteRef []byte

// Update updates the byte in the buffer
func (ref ByteRef) Update(b byte) {
	if ref != nil {
		ref[0] = b
	}
}

// A Uint16Ref is a reference to a uint16 placeholder in a buffer
type Uint16Ref []byte

// Update updates the uint16 in the buffer
func (ref Uint16Ref) Update(n uint16) {
	if ref != nil {
		binary.BigEndian.PutUint16(ref, n)
	}
}

// A Uint32Ref is a reference to a uint32 placeholder in a buffer
type Uint32Ref []byte

// Update updates the uint32 in the buffer
func (ref Uint32Ref) Update(n uint32) {
	if ref != nil {
		binary.BigEndian.PutUint32(ref, n)
	}
}

// A Uint64Ref is a reference to a uin64 placeholder in a buffer
type Uint64Ref []byte

// Update updates the uint64 in the buffer
func (ref Uint64Ref) Update(n uint64) {
	if ref != nil {
		binary.BigEndian.PutUint64(ref, n)
	}
}

// A BytesRef is a reference to a multi-byte placeholder in a buffer
type BytesRef []byte

// Update updates the bytes in the buffer
func (ref BytesRef) Update(b []byte) {
	if ref != nil {
		copy(ref, b)
	}
}

// UpdateString updates the bytes in the buffer from a string
func (ref BytesRef) UpdateString(s string) {
	if ref != nil {
		copy(ref, s)
	}
}


text:
/**
 * We'll load the axios HTTP library which allows us to easily issue requests
 * to our Laravel back-end. This library automatically handles sending the
 * CSRF token as a header based on the value of the "XSRF" token cookie.
 */

window.axios = require('axios');

window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';

/**
 * Next we will register the CSRF Token as a common header with Axios so that
 * all outgoing HTTP requests automatically have it attached. This is just
 * a simple convenience so we don't have to attach every token manually.
 */

let token = document.head.querySelector('meta[name="csrf-token"]');

if (token) {
    window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
} else {
    console.error('CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token');
}

redpajama_set_name: RedPajamaGithub


text: A test project for SonarQube issues


text:
package io.pimwi.application.controllers;

import io.pimwi.domain.entities.Person;
import io.pimwi.domain.entities.Session;
import io.pimwi.domain.services.PersonService;
import io.pimwi.domain.services.SessionService;
import io.pimwi.infra.util.ApplicationException;
import io.pimwi.infra.util.CookieHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.inject.Inject;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import java.util.List;

/**
 * User: OCTO-JBU
 * Date: 04/04/2014
 * Time: 20:31
 */
@Controller
@RequestMapping("/search")
public class SearchPageController {

    private static final Logger LOGGER = LoggerFactory.getLogger(NewsPageController.class);

    @Inject
    SessionService sessionService;

    @Inject
    PersonService personService;

    @RequestMapping(method = RequestMethod.GET)
    public String doGet(HttpServletRequest request, ModelMap model, String query) {
        Cookie cookie = CookieHelper.get(request, Session.SMART_SESSION_ID);
        if (cookie != null) {
            String token = cookie.getValue();
            Session session = sessionService.getSession(token);
            if (session != null) {
                try {
                    List<Person> persons = personService.find(token, query);
                    model.addAttribute("persons", persons);
                    return "search";
                } catch (ApplicationException e) {
                    return "redirect:/error";
                }
            }
        }
        return "redirect:/error";
    }

}


text:
/* eslint-disable no-inner-declarations */
/* eslint-disable @typescript-eslint/no-namespace */

import * as reflection from "./reflection"
import * as _ from "lodash"
import * as stringHelper from "./str"
import * as dsv from "d3-dsv"
import * as time from "./time"
import * as exception from "./exception"

/** parse comma or tab seperated values.   see https://www.npmjs.com/package/d3-dsv
	*
	This module provides a parser and formatter for delimiter-separated values, most commonly comma- (CSV) or tab-separated values (TSV). These tabular formats are popular with spreadsheet programs such as Microsoft Excel, and are often more space-efficient than JSON. This implementation is based on RFC 4180.

Comma (CSV) and tab (TSV) delimiters are built-in. For example, to parse:
```
d3.csvParse("foo,bar\n1,2"); // [{foo: "1", bar: "2"}, columns: ["foo", "bar"]]
d3.tsvParse("foo\tbar\n1\t2"); // [{foo: "1", bar: "2"}, columns: ["foo", "bar"]]
```
Or to format:
```
d3.csvFormat([{foo: "1", bar: "2"}]); // "foo,bar\n1,2"
d3.tsvFormat([{foo: "1", bar: "2"}]); // "foo\tbar\n1\t2"
```
To use a different delimiter, such as "|" for pipe-separated values, use d3.dsvFormat:
```
var psv = d3.dsvFormat("|");

console.log(psv.parse("foo|bar\n1|2")); // [{foo: "1", bar: "2"}, columns: ["foo", "bar"]]
```
	*/
export { dsv }

import * as json5 from "json5"
//export const json5: JSON = _json5 as ANY

/** awesome json parse and stringify capabilities */
export namespace jsonX {

	/** a forgiving JSON parser.  Allows for comments, unquoted keys, trailing commas, etc.   see: https://www.npmjs.com/package/json5
		*
							* Converts a JavaScript Object Notation (JSON) string into an object.
							* @param text A valid JSON string.
							* @param reviver A function that transforms the results. This function is called for each member of the object.
							* If a member contains nested objects, the nested objects are transformed before the parent object is.
							*/
	export const parse: typeof JSON.parse = json5.parse.bind( json5 ) //  ( text: string, reviver?: ( key: ANY, value: ANY ) => ANY ) => ANY = json5.parse.bind( json5 );

	/** parses your object using ```json5```, then attempts to parse string values in your object.  failed parse() calls will return the original string for that variable */
	export function parseRecursive(
		textOrObj: ANY,
		reviver?: ( key: ANY, value: ANY ) => ANY
	): ANY {

		if ( typeof ( textOrObj ) === "string" ) {
			try {
				textOrObj = parse( textOrObj, reviver )
			} catch ( ex ) {
				return textOrObj
			}
		}
		_.forOwn( textOrObj, ( value, key, obj ) => {
			if ( typeof ( value ) === "string" ) {
				obj[ key ] = parseRecursive( value, reviver )
			}
		} )

		return textOrObj
	}

	/**
			* Converts a JavaScript value to a JSON5 string, optionally replacing values if a replacer function is specified, or optionally including only the specified properties if a replacer array is specified.
			* @param value The value to convert to a JSON5 string.
			* @param replacer A function that alters the behavior of the stringification process, or an array of String and Number objects that serve as a whitelist for selecting/filtering the properties of the value object to be included in the JSON5 string. If this value is null or not provided, all properties of the object are included in the resulting JSON5 string.
			* @param space A String or Number object that's used to insert white space into the output JSON5 string for readability purposes. If this is a Number, it indicates the number of space characters to use as white space; this number is capped at 10 (if it is greater, the value is just 10). Values less than 1 indicate that no space should be used. If this is a String, the string (or the first 10 characters of the string, if it's longer than that) is used as white space. If this parameter is not provided (or is null), no white space is used. If white space is used, trailing commas will be used in objects and arrays.  @default "\t"
		 * @param quote  A String representing the quote character to use when serializing strings.
			*/
	export function stringify( value: ANY,
		replacer?: ( key: string, value: ANY ) => ANY | Array<number | string>,
		space?: string | number,
		quote?: string,
	): string;
	export function stringify( value: ANY, options?: {
		replacer?: ( key: string, value: ANY ) => ANY | Array<number | string>;
		space?: string | number;
		quote?: string;
	} ): string;
	export function stringify( value: ANY, ...args: Array<ANY> ) {
		let options: {
			replacer?: ( key: string, value: ANY ) => ANY | Array<number | string>;
			space?: string | number;
			quote?: string;
		}

		if ( reflection.getType( args[ 0 ] ) === reflection.Type.object ) {
			options = args[ 0 ]
		} else {
			options = {
				replacer: args[ 0 ],
				space: _.defaultTo( args[ 1 ], "\t" ),
				quote: args[ 2 ],
			}
		}
		return json5.stringify( value, options )
	}

	export interface IInspectOptions {
		/** how far down the object structure you wish to inspect.  No values deeper than the depth will be shown.  @default 1 (show current object's values, no children)*/
		maxDepth?: number;
		/** maximum array elements you want to display for each array. (half at top, half at bottom)  @default 10 */
		maxArrayElements?: number;
		/** when we reach maxDepth, the length we summarize the values to.  @default 120 */
		summarizeLength?: number;

		/** true to group all functions into a single string value  (reduce verbosity).  @default false */
		aggrigateFunctions?: boolean;

		/** true to not show typeNames we don't have a ```typeProcessor``` for. (Note that POJO objects will not have their typeName ("Object") shown regardless)*/
		hideTypeNames?: boolean;

		/** allows custom parsing of your own types.  return ```undefined``` or ```null``` to do default processing*/
		typeProcessor?: ( value: ANY, type: reflection.Type, typeName: string, key: string, options: IInspectOptions ) => ANY;

	}

	export function inspectStringify( obj: ANY, options?: IInspectOptions
	) {
		const outputJson = inspectParse( obj, options )
		return JSON.stringify( outputJson, undefined, "  " )
	}
	/** debug inspection helper. outputs human readable JSON (but won't round-trip with .parse()).  handles circular references gracefully */
	export function inspectParse( obj: ANY, options?: IInspectOptions ) {

		options = { maxArrayElements: 10, maxDepth: 1, summarizeLength: 120, ...options }

		return _inspectParse_internal( obj, options as Required<IInspectOptions>, [], "" )
	}
	/** internal helper to do actual parse work */
	function _inspectParse_internal( obj: ANY, parentOptions: Required<IInspectOptions>,
		/** for internal recursive use, tracking circular references. */
		parentSeenObjects: ANY,
		key: string
	): ANY {
		const myOptions = _.clone( parentOptions )
		try {
			myOptions.maxDepth--
			// ! circular reference detection
			/** cache of all objects to check for circular references.   see https://stackoverflow.com/questions/14962018/detecting-and-fixing-circular-references-in-javascript */
			const seenObjects = _.clone( parentSeenObjects )
			if ( _.isObject( obj ) ) {
				if ( parentSeenObjects.indexOf( obj ) !== -1 ) {
					return `[CIRCULAR REFERENCE type=${ reflection.getTypeName( obj ) }]`
				}
				seenObjects.push( obj )
			}

			// ! output string value of node if possible
			const Type = reflection.Type
			const type = reflection.getType( obj )
			//if it's well known types, generate friendly values
			const typeName = reflection.getTypeName( obj )

			if ( myOptions.typeProcessor != null ) {
				const customProcessorResult = myOptions.typeProcessor( obj, type, typeName, key, myOptions )
				if ( customProcessorResult != null ) {
					return customProcessorResult
				}
			}

			switch ( type ) {
				case Type.boolean:
				case Type.number:
				case Type.null:
					return obj
				case Type.symbol:
					if ( Symbol.keyFor( obj ) != null ) {
						return obj.toString() + "[GLOBAL]"
					} else {
						return obj.toString()
					}
				case Type.undefined:
					return "[UNDEFINED]"
				case Type.string:
					return stringHelper.summarize( obj, myOptions.summarizeLength )
				case Type.Date:
					{
						const asDate = obj as Date
						//	return asDate.toISOString();
						//const ago = time.luxon.DateTime.fromJSDate( asDate ).until( time.luxon.DateTime.utc() ).toDuration().toFormat( "hh:mm:ss.SS" );

						const diffNow = time.dayjs( asDate ).diff( Date.now() )  // .luxon.DateTime.fromMillis( asDate.valueOf() ).diffNow()
						//let ago = diffNow.toISO();
						//  let ago = diffNow.valueOf() < 0 ? "-" : "";
						// ago += diffNow.toFormat( "hh:mm:ss.SS" );
						const ago = time.dayjs.duration( diffNow ).format( "hh:mm:ss.SS" )
						// //numHelper.format((Date.now()-asDate.getTime())/1000)
						return `${ asDate.toISOString() } (deltaNow:${ ago })`
					}
				case Type.Error: {
					const errOptions = { ...myOptions, maxDepth: myOptions.maxDepth + 1 }
					//retry using an error JSON
					return _inspectParse_internal( exception.errorToJson( obj ), errOptions, seenObjects, key )
				}
				case Type.function:
					{
						// eslint-disable-next-line @typescript-eslint/ban-types
						const asFunction = obj as Function
						let funcStr = asFunction.toString()
						funcStr = stringHelper.removeAfter( funcStr, ")", true )
						funcStr = "[FUNCTION " + stringHelper.removeBefore( funcStr, "function " ) + "]"
						return stringHelper.summarize( funcStr, myOptions.summarizeLength )
					}
				case Type.RegExp:
					{
						const asRegEx = obj as RegExp
						return stringHelper.summarize( asRegEx.toString(), myOptions.summarizeLength )
					}
				case Type.classCtor:
					return `[CLASS ${ reflection.getTypeName( obj ) }]`
				default:
					return `[INSPECT_TYPE_NOT_HANDLED  type=${ Type[ type ] }]`
				case Type.Array:
				case Type.object:
					{

						if ( obj.asMilliseconds != null ) {
							//guess it's a duration object of some sort
							const ms = obj.asMilliseconds()
							return time.dayjs.duration( ms ).format( "hh:mm:ss.SS" )
						}

						if ( obj.toISOString != null && obj.year != null ) {
							//guess it's a date object of some sort
							const asDate = time.dayjs( obj.toISOString() )
							const diffNow = time.dayjs.duration( asDate.diff( Date.now() ) ) //time.luxon.DateTime.fromMillis( asDate.valueOf() ).diffNow()
							const ago = diffNow.format( "hh:mm:ss.SS" )
							return `${ asDate.toISOString() } (deltaNow:${ ago })`

						}

						//handle specific known types
						switch ( typeName ) {
							// case "Duration":
							// case "DateTime":

							// 	if ( obj.valueOf != null ) {
							// 		const asDate = new Date( obj.valueOf() )
							// 		const diffNow = time.luxon.DateTime.fromMillis( asDate.valueOf() ).diffNow()
							// 		//let ago = diffNow.toISO();
							// 		// let ago = diffNow.valueOf() < 0 ? "-" : "";
							// 		// ago += diffNow.toFormat( "hh:mm:ss.SS" );
							// 		const ago = diffNow.toFormat( "hh:mm:ss.SS" )
							// 		// //numHelper.format((Date.now()-asDate.getTime())/1000)
							// 		return `${ asDate.toISOString() } (deltaNow:${ ago })`
							// 	}
							// 	break
							case "Timeout":
								return "[Timer Handle (typename=\"Timeout\")]"
						}

						//for other object cases, we need to recursively walk them.   see below
						break
					}
			}

			// ! the obj is an array, or object

			if ( myOptions.maxDepth < 0 ) {
				//at max depth.  output typename
				if ( type === Type.Array ) {
					const asArray = obj as Array<any>
					return `[ARRAY len=${ asArray.length }]`
				} else {
					return `[OBJECT typeName="${ reflection.getTypeName( obj ) }"]`
				}
			}

			const testMap = new Map<string, number>()
			const testSet = new Set<number>()
			const testArray = []
			//testArray.forE
			//testSet.forEach()
			// //testMap

			let arrayOrigType = "ARRAY"
			try {
				/** if this has a forEach method and not an array, convert it to an array for parsing */
				if ( _.isArray( obj ) === false && obj.forEach != null && typeof ( obj.forEach ) === "function" ) {
					arrayOrigType = reflection.getTypeName( obj )
					const tempArray: any[] = []
					obj.forEach( ( val: any, key: any ) => {
						if ( val === key || key === obj ) {
							//if no key, just push val
							tempArray.push( val )
						} else {
							tempArray.push( { key, val } )
						}
					} )
					obj = tempArray
				}
			} catch {
				//eat errors
			}

			//if there are symbols present, convert those to keys that can be inspected.
			const symbols = Object.getOwnPropertySymbols( obj )
			if ( symbols != null && symbols.length > 0 ) {
				obj = _.clone( obj )
				for ( let i = 0; i < symbols.length; i++ ) {
					obj[ symbols[ i ].toString() ] = obj[ symbols[ i ] ]
					// tslint:disable-next-line: no-dynamic-delete
					delete obj[ symbols[ i ] ]
				}
			}

			//recursivly walk children
			if ( _.isArray( obj ) === true ) {
				const objArray = obj as Array<ANY>
				const toReturn = []
				if ( objArray.length <= myOptions.maxArrayElements ) {
					//output all
					for ( let i = 0; i < objArray.length; i++ ) {
						toReturn.push( _inspectParse_internal( objArray[ i ], myOptions, seenObjects, i.toString() ) )
					}
				} else {
					//output top and bottom

					//top half
					const halfMax = Math.round( myOptions.maxArrayElements / 2 )
					for ( let i = 0; i < halfMax; i++ ) {
						toReturn.push( _inspectParse_internal( objArray[ i ], myOptions, seenObjects, i.toString() ) )
					}
					//missing middle
					toReturn.push( `[${ arrayOrigType }_TRUNCATED len=${ objArray.length }]` )
					//bottom half
					for ( let i = 0; i < halfMax; i++ ) {
						const index = objArray.length - halfMax + i
						if ( index < objArray.length ) {
							toReturn.push( _inspectParse_internal( objArray[ index ], myOptions, seenObjects, index.toString() ) )
						}
					}
				}
				// for ( let i = 0; i < objArray.length && i < maxArrayElements; i++ ) {
				// 	toReturn.push( inspect( objArray[ i ], maxDepth, maxArrayElements, summarizeLength ) );
				// }
				// if ( objArray.length > maxArrayElements ) {
				// 	toReturn.push( `*maxArrayElements reached.  len=${ objArray.length }*` );
				// }

				return toReturn
			} else {
				//loop through object
				const functs: Array<string> = []
				const toReturn: { [ key: string ]: ANY; } = {}
				_.forIn( obj, ( value, key ) => {
					const val = _inspectParse_internal( value, myOptions, seenObjects, key )

					//reduce verbosity of functions in the object
					if ( myOptions.aggrigateFunctions === true && ( typeof val === "string" ) && val.indexOf( "[FUNCTION" ) === 0 ) {
						const results = /^\[FUNCTION\s*([\S\s]{1,})\]$/.exec( val )
						if ( results != null ) {
							const funcDetails = results[ 1 ]
							if ( funcDetails.indexOf( key ) === 0 ) {
								//name of func is name as key, so don't display the redundant key
								functs.push( results[ 1 ] )
							} else {
								//function name is different display key
								functs.push( `${ key }=${ results[ 1 ] }` )
							}
						} else {
							//didnt' work, report it normally
							toReturn[ key ] = val
						}

					} else {
						toReturn[ key ] = val
					}
				} )
				if ( functs.length > 0 ) {
					toReturn[ `[FUNCTIONS count=${ functs.length }]` ] = functs.join( ", " )
				}
				if ( myOptions.hideTypeNames !== true ) {
					const typeName = reflection.getTypeName( obj )
					if ( typeName !== "Object" ) {
						toReturn[ "[TYPENAME]" ] = typeName
					}
				}

				return toReturn
			}

		} catch ( _err ) {
			const err = exception.toError( _err )
			return `[ERROR_PARSING name="${ err.name }", message="${ stringHelper.summarize( err.message, myOptions.summarizeLength ) }"]`
		}

	}  //end fcn

	/** replace a branch of your JSON object.  good for pruning nested hiearchies, for example when wanting to decrease verbosity sent to user (before doing a JSON.stringify() )
		*
		* works on array children too
	*
	* @example
	let tree = { a:[{aa:0, ab:1}], b:{ ba:"hi", bb:"there"}};
	replaceNodes(tree, ["a.aa", "b.ba"],"*REMOVED*");
	// tree = {a[aa:"*REMOVED*",ab:1], b:{ ba:"*REMOVED", bb:"there"}};
		*/
	export function replaceNodes( targetObject: ANY,
		/** example:  'a.b.c.d' will remove the d node, replacing it (with null by default, effectively deleting)*/
		nodeHiearchyStrings: Array<string>, replaceWith: ANY = null, replaceEmptyLeafNodes: boolean = false ) {

		/** recursive helper for walking through the current hiearchy, replacing as it goes*/
		function currentNodeProcessor( previousNode: ANY, nodeName: string, hiearchyIndex: number, hiearchy: Array<string> ) {

			if ( previousNode == null || _.isString( previousNode ) ) {
				//if our previous node is null (or a string), nothing to do.
				return
			}

			if ( hiearchyIndex === ( hiearchy.length - 1 ) ) {
				//the node is the last node in our hiearchy,
				//so we are on the node to remove.remove it and we are done
				if ( previousNode[ nodeName ] != null || replaceEmptyLeafNodes === true ) {
					previousNode[ nodeName ] = replaceWith
				}
				return
			}

			//walk down the hiearchy
			const thisNode = previousNode[ nodeName ]
			const nextHiearchyIndex = hiearchyIndex + 1
			const nextNodeName = hiearchy[ nextHiearchyIndex ]
			if ( _.isArray( thisNode ) === true && _.isString( thisNode ) === false ) {
				//walk each element in the array automatically
				_.forEach( thisNode, ( element ) => {
					currentNodeProcessor( element, nextNodeName, nextHiearchyIndex, hiearchy )
				} )
				return
			} else {
				currentNodeProcessor( thisNode, nextNodeName, nextHiearchyIndex, hiearchy )
			}

		}

		//loop through all nodeHiearchyStrings to remove, removing the leaf.
		_.forEach( nodeHiearchyStrings, ( hiearchyString ) => {
			if ( hiearchyString == null ) {
				return
			}

			const hiearchy = hiearchyString.split( "." )

			if ( hiearchy.length < 1 ) {
				return
			}

			currentNodeProcessor( targetObject, hiearchy[ 0 ], 0, hiearchy )

		} )
	}
}

/** constructor for async functions.
 * from: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/AsyncFunction
 */
const AsyncFunction: FunctionConstructor = Object.getPrototypeOf( async function () { } ).constructor

/** deseralize a function that was serialized via ```.toString()```.  Works on lambda functions also. */
export function parseFunction( fcnStr: string ) {
	//citation: https://gist.github.com/lamberta/3768814  but then heavily modified for proper lambda support

	fcnStr = fcnStr.trim()

	//! handle possible async function
	let FcnCtor = Function
	if ( fcnStr.startsWith( "async" ) ) {
		fcnStr = stringHelper.removePrefix( fcnStr, "async" )
		fcnStr = fcnStr.trim()
		FcnCtor = AsyncFunction
	}

	if ( fcnStr.startsWith( "function" ) ) {
		const fn_body_idx = fcnStr.indexOf( "{" )
		const fn_body = fcnStr.substring( fn_body_idx + 1, fcnStr.lastIndexOf( "}" ) ).trim()
		const fn_declare = fcnStr.substring( 0, fn_body_idx )
		const fn_params_start = fn_declare.indexOf( "(" ) + 1
		const fn_params = fn_declare.substring( fn_params_start, fn_declare.lastIndexOf( ")" ) )
		const args = fn_params.split( "," )

		args.push( fn_body )

		const toReturn = new FcnCtor( ...args )
		return toReturn
	} else {
		//lambda
		const fn_params = fcnStr.substring( fcnStr.indexOf( "(" ) + 1, fcnStr.indexOf( ")" ) )
		const args = fn_params.split( "," )

		let fn_body_idx = fcnStr.indexOf( "=>" ) + 2
		let fn_body_end = fcnStr.length

		if ( fcnStr.endsWith( "}" ) ) {
			//enclosed lambda body so remove surrounding braces
			fn_body_idx = fcnStr.indexOf( "{", fn_body_idx ) + 1
			fn_body_end--
			const fn_body = fcnStr.substring( fn_body_idx, fn_body_end )
			args.push( fn_body )
		} else {
			const fn_body = "return " + fcnStr.substring( fn_body_idx, fn_body_end )
			args.push( fn_body )
		}

		const toReturn = new FcnCtor( ...args )
		return toReturn
	}
}


text:
let Table = require("uxcore-table");
let Button = require('uxcore-button');
let Form = require('uxcore-form');
let Dialog = require('uxcore-dialog');
let classnames = require("classnames");
let DeleteDialog = require("./delete-dialog");
const Formatter = require('uxcore-formatter');
/*
 * 讲解:从 Form 中取出 Form 的零件用以配置生成一个完整的 Form。
 * Form 的使用文档见:http://uxco.re/components/form/
 */
let {FormRow, InputFormField, OtherFormField, DateFormField, Validators, NumberInputFormField, SelectFormField} = Form;

class RoleTable extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            value: {
                style: 'border',
                size: 'small',
            },
            showAdSearch: false,
            fetchParams: {},
            editShow: false,
            newShow: false,
            memberShow: false,
            delMemberShow: false,
            deleteRoleUser: null,
            editValues: null,
        }
    }

    handleSearchAdClick() {
        let me = this;
        me.setState({
            showAdSearch: !me.state.showAdSearch
        });
    }

    handleSearch() {
        let me = this;
        let data = me.refs.searchForm.getValues();
        me.setState({
            fetchParams: data.values
        }, function () {
            me.refs.table.fetchData();
        })
    }

    handleAdSearch() {
        let me = this;
        let data = me.refs.searchAdForm.getValues();
        me.setState({
            fetchParams: data.values
        }, function () {
            me.refs.table.fetchData();
        })
    }

    handleResetClick() {
        let me = this;
        me.refs.searchAdForm.resetValues();
    }

    toggleShow(key) {
        let me = this;
        let obj = {};
        obj[key] = !me.state[key];
        me.setState(obj);
    }

    handleEditOk() {
        let me = this;
        let data = me.refs.editForm.getValues();
        if (data.pass) {
            $.ajax({
                url: ctp + '/role/' + data.values.roleId,
                method: 'put',
                data: data.values,
                success: function (result) {
                    if (result.success) {
                        me.toggleShow('editShow');
                        me.refs.table.fetchData();
                    }
                }
            })
        }
    }

    handleEditCancel() {
        let me = this;
        me.refs.editForm.resetValues();
        me.toggleShow('editShow');
    }

    handleNewOk() {
        let me = this;
        let data = me.refs.editForm.getValues();
        if (data.pass) {
            $.ajax({
                url: ctp + '/role',
                method: 'post',
                data: data.values,
                success: function (result) {
                    if (result.success) {
                        me.toggleShow('newShow');
                        me.refs.table.fetchData();
                        me.refs.editForm.resetValues();
                    }
                }
            })
        }
    }

    handleNewCancel() {
        let me = this;
        me.toggleShow('newShow');
        me.refs.editForm.resetValues();
    }

    showEditDialog(rowData) {
        this.setState({
            editShow: true,
            editValues: rowData
        });
    }

    showDialog(key) {
        let me = this;
        let obj = {};
        obj[key] = !me.state[key];
        obj['editValues'] = {};
        me.setState(obj);
    }

    formatDate(value, format) {
        if (isNaN(value) || value === null) {
            return value;
        }
        return Formatter.date(value, format);
    }

    showDeleteUserDialog(rowData) {
        let me = this;
        me.setState({
            delMemberShow: true,
            deleteRoleUser: rowData
        });
    }

    showMemberDialog(rowData) {
        let me = this;
        me.setState({
            memberShow: true,
            editValues: rowData
        });
    }

    handleHideMemberDialog() {
        let me = this;
        me.setState({
            memberShow: false,
            editValues: null
        });
    }

    handleMemberDeleteCancel(){
        let me = this;
        me.setState({
            delMemberShow: false
        })
    }

    handleMemberDeleteOk() {
        let me = this;
        let selectedItems = me.state.deleteRoleUser || [];
        let keys = [];
        selectedItems.forEach(function (value, index, array) {
            keys.push(value.userId);
        });
        $.ajax({
            url: ctp + "/role/members/" + me.state.editValues.roleId,
            method: 'post',
            traditional: true,
            data: {id: keys},
            success: function (res) {
                if (res.success) {
                    selectedItems.forEach(function (value) {
                        me.refs.memberTable.delRow(value);
                    });
                    me.setState({
                        delMemberShow: false
                    })
                }
            }
        })
    }

    render() {
        let me = this;

        let columns = [
            {dataKey: 'roleId', title: 'ID', width: 50, hidden: true},
            {dataKey: 'roleName', title: '角色名称', width: 200, ordered: true},
            {dataKey: 'roleKey', title: '角色编码', width: 200, ordered: true},
            {
                dataKey: 'action', title: '操作', width: 250, type: 'action', rightFixed: true,
                actions: {
                    '编辑': function (rowData, actions) {
                        me.showEditDialog(rowData);
                    },
                    '成员管理': function (rowData, actions) {
                        me.showMemberDialog(rowData);
                    },
                    '删除': function (rowData) {
                        me.refs.deleteDialog.show([rowData]);
                    }
                }
            }
        ];

        let tableProps = {
            fetchUrl: ctp + "/role/table",
            jsxcolumns: columns,
            renderModel: 'tree',
            fetchParams: me.state.fetchParams,
            actionBar: {
                '新增': function () {
                    me.showDialog('newShow');
                },
                '删除': function () {
                    me.refs.deleteDialog.show();
                }
            },
            beforeFetch: function (data, from) {
                if (data.createAt) {
                    data.createAtBegin = me.formatDate(data.createAt[0], 'yyyy-MM-DD');
                    data.createAtEnd = me.formatDate(data.createAt[1], 'yyyy-MM-DD');
                    delete data.createAt;
                }
                return data;
            },
            rowSelection: {
                onSelect: function (record, selected, selectedRows) {
                    me.selected = selectedRows;
                },
                onSelectAll: function (selected, selectedRows) {
                    me.selected = selectedRows;
                }
            }
        };

        let form = <Form className="" jsxvalues={me.state.editValues} ref="editForm">
            <FormRow>
                <InputFormField jsxlabel="角色名称" jsxname="roleName"
                                jsxrules={{validator: Validators.isNotEmpty, errMsg: "非空"}}/>
                <InputFormField jsxname="roleId" jsxshow={false}/>
            </FormRow>
            <FormRow>
                <InputFormField jsxlabel="角色编码" jsxname="roleKey"/>
            </FormRow>
        </Form>;

        let memberTableProps = {
            fetchUrl: ctp + "/role/members/" + (me.state.editValues ? me.state.editValues.roleId : 0),
            jsxcolumns: [
                {dataKey: 'userId', title: 'ID', width: 50, hidden: true},
                {dataKey: 'userName', title: '用户名', width: 200, ordered: true},
                {dataKey: 'lastLoginAt', title: '最后登录时间', width: 150, ordered: true},
                {
                    dataKey: 'action', title: '操作', width: 200, type: 'action',
                    actionType: this.state.value.action,
                    collapseNum: this.state.value.num || 3, // 超过 3 个将开始折叠
                    actions: {
                        '删除': function (rowData) {
                            me.showDeleteUserDialog([rowData]);
                        }
                    }
                }
            ],
            fetchParams: me.state.fetchParams,
            actionBar: {
                '删除': function () {
                    me.showDeleteUserDialog(me.selectedUser);
                }
            },
            rowSelection: {
                onSelect: function (record, selected, selectedRows) {
                    me.selectedUser = selectedRows;
                },
                onSelectAll: function (selected, selectedRows) {
                    me.selectedUser = selectedRows;
                }
            }
        };
        let memberTable =
;

        return (

角色管理

                <Form ref="searchForm" className="search-form">
                    <FormRow>
                        <InputFormField jsxname="roleName" jsxshowLabel={false} jsxplaceholder="输入角色名称字进行查询"/>
                        <OtherFormField className="search-container">
                            <Button onClick={me.handleSearch.bind(me)}>查询</Button>

                                高级查询

                        </OtherFormField>
                    </FormRow>
                </Form>
                <Form ref="searchAdForm" className="search-form">
                    <FormRow className={classnames({"hidden": !me.state.showAdSearch, "show": me.state.showAdSearch})}>
                        <InputFormField jsxlabel="角色名称" jsxname="roleName"/>
                        <InputFormField jsxlabel="角色编码" jsxname="roleKey"/>
                    </FormRow>
                    <FormRow className={classnames({"hidden": !me.state.showAdSearch, "show": me.state.showAdSearch})}>
                        <DateFormField jsxlabel="创建日期" jsxname="createAt" jsxtype="cascade" autoMatchWidth={true}
                                       format={'yyyy-MM-DD'}/>
                        <OtherFormField className="searchButton">
                            <Button type="primary" onClick={me.handleAdSearch.bind(me)}>提交</Button>
                            <Button type="secondary" onClick={me.handleResetClick.bind(me)}>重置</Button>
                        </OtherFormField>
                    </FormRow>
                </Form>

                <Dialog ref="editDialog" width={500} visible={me.state.editShow} title="角色编辑"
                        onOk={me.handleEditOk.bind(me)} onCancel={me.handleEditCancel.bind(me)}>
                    {form}
                </Dialog>
                <Dialog ref="memberDialog" width={500} visible={me.state.memberShow} title="成员管理"
                        onOk={me.handleHideMemberDialog.bind(me)} onCancel={me.handleHideMemberDialog.bind(me)}>
                    {memberTable}
                </Dialog>
                <Dialog ref="newDialog" width={500} visible={me.state.newShow} title="角色新增"
                        onOk={me.handleNewOk.bind(me)} onCancel={me.handleNewCancel.bind(me)}>
                    {form}
                </Dialog>
                <DeleteDialog ref="deleteDialog" {... {
                    url: "/role/delete",
                    id: 'roleId',
                    text: 'roleName',
                    table: me,
                    tableName: 'table'
                }} />
                <Dialog ref="delMemberDialog" width={200} visible={me.state.delMemberShow} title="确认删除?"
                        onOk={me.handleMemberDeleteOk.bind(me)} onCancel={me.handleMemberDeleteCancel.bind(me)}>
                </Dialog>

        )
    }

}

export default RoleTable;


text:
`xdebug` extension is disabled by default as it causes about 20% performance hit.

There two variants: you can use xdebug for debuging requests from browser or you can debug requests from console (for example Drush commands).

For configuration first variant use **Prerequisites** and **Setup**.

For configuration second variant use **Setup for console php**.

## Prerequisites

- [PHPStorm](https://www.jetbrains.com/phpstorm/)
- [Xdebug Helper](https://chrome.google.com/extensions/detail/eadndfjplgieldjbigjakmdgkmoaaaoc) extension for Chrome

    You can also pick from the [list](https://confluence.jetbrains.com/display/PhpStorm/Browser+Debugging+Extensions) of options for other browsers

## Setup

1. Set environment variable on the `cli` service

    ```yml
    cli:
      ...
      environment:
        - XDEBUG_ENABLED=1
      ...
    ```
2. Update container configuration with `dsh up`
3. Open your project in PHPStorm
4. Set a breakpoint wherever you like
5. Click on the **Start Listening for PHP Debug Connections** button in PHPStorm

6. Click on **Debug** in **Xdebug Helper** in Chrome

7. Click on **Accept** in the **Incoming Connection From Xdebug** dialogue in PHPStorm

Happy debugging!

## Setup for console php
1. Set environment variable on the `cli` service

    ```yml
    cli:
      ...
      environment:
        - XDEBUG_ENABLED=1
        - XDEBUG_CONFIG=idekey=PHPSTORM remote_host=192.168.10.1
        - PHP_IDE_CONFIG=serverName=drupal7.drude
      ...
    ```
   You need to replace **drupal7.drude** with your domain. You can find it in `web` section:
   ```yml
   web:
     ...
     environment:
       - VIRTUAL_HOST=drupal7.drude
     ...
     ...
   ```

2. Update container configuration with `dsh up`
3. You can run your scripts from console and debug it in the same way as requests from browser.

For example you can run drush command:

    ```bash
    dsh drush fra -y
    ```

and debug this drush command from feature module.

### Resources

- [Zero-configuration Web Application Debugging with Xdebug and PhpStorm](https://confluence.jetbrains.com/display/PhpStorm/Zero-configuration+Web+Application+Debugging+with+Xdebug+and+PhpStorm)


text:
var should = require('should');
var util = require('util');
var testUtils = require('../util/util');
var CLITest = require('../framework/cli-test');

var suite;
var vmPrefix = 'clitestvm';
var testPrefix = 'cli.vm.create_loc_vnet_vm-tests';

var requiredEnvironment = [{
  name: 'AZURE_VM_TEST_LOCATION',
  defaultValue: 'West US'
}];

describe('cli', function() {
  describe('vm', function() {
    var affinityName = 'xplataffintest',
      vmVnetName,
      timeout,
      affinLabel = 'xplatAffinGrp',
      affinDesc = 'Test Affinty Group for xplat',
      location,
      userName = 'azureuser',
      password = 'Pa$$word@123',
      retry = 5;
    testUtils.TIMEOUT_INTERVAL = 10000;

    var vmToUse = {
      Name: null,
      Created: false,
      Delete: false
    };

    before(function(done) {
      suite = new CLITest(testPrefix, requiredEnvironment);
      suite.setupSuite(done);
    });

    after(function(done) {
      suite.teardownSuite(done);
    });

    beforeEach(function(done) {
      suite.setupTest(function() {
        location = process.env.AZURE_VM_TEST_LOCATION;
        vmVnetName = suite.isMocked ? 'xplattestvmVnet' : suite.generateId(vmPrefix, null) + 'Vnet';
        timeout = suite.isMocked ? 0 : testUtils.TIMEOUT_INTERVAL;
        done();
      });
    });

    afterEach(function(done) {
      function deleteUsedVM(vm, callback) {
        if (vm.Created && vm.Delete) {
          setTimeout(function() {
            var cmd = util.format('vm delete %s -b -q --json', vm.Name).split(' ');
            testUtils.executeCommand(suite, retry, cmd, function(result) {
              result.exitStatus.should.equal(0);
              vm.Name = null;
              vm.Created = vm.Delete = false;
              callback();
            });
          }, timeout);
        } else {
          callback();
        }
      }

      deleteUsedVM(vmToUse, function() {
        suite.teardownTest(done);
      });
    });

    //create a vm with affinity group, vnet and availibilty set
    describe('Create:', function() {
      it('Vm should create with vnet and location', function(done) {
        getImageName('Linux', function(imageName) {
          getVnet('Created', function(virtualnetName, affinityName) {
            var cmd = util.format('account affinity-group show %s --json', affinityName).split(' ');
            testUtils.executeCommand(suite, retry, cmd, function(result) {
              result.exitStatus.should.equal(0);
              var vnetObj = JSON.parse(result.text);
              cmd = util.format('vm create -w %s %s %s %s %s --json', virtualnetName, vmVnetName, imageName, userName, password).split(' ');
              cmd.push('-l');
              cmd.push(vnetObj.location);
              testUtils.executeCommand(suite, retry, cmd, function(result) {
                result.exitStatus.should.equal(0);
                vmToUse.Created = true;
                vmToUse.Name = vmVnetName;
                vmToUse.Delete = true;
                done();
              });
            });
          });
        });
      });

      it('Vm should create with vnet', function(done) {
        getImageName('Linux', function(imageName) {
          getVnet('Created', function(virtualnetName, affinityName) {
            var cmd = util.format('vm create --ssh -w %s %s %s %s %s --json',
              virtualnetName, vmVnetName, imageName, userName, password).split(' ');
            testUtils.executeCommand(suite, retry, cmd, function(result) {
              result.exitStatus.should.equal(0);
              vmToUse.Created = true;
              vmToUse.Name = vmVnetName;
              vmToUse.Delete = true;
              done();
            });
          });
        });
      });
    });

    // Get name of an image of the given category
    function getImageName(category, callBack) {
      if (process.env.VM_LINUX_IMAGE) {
        callBack(process.env.VM_LINUX_IMAGE);
      } else {
        var cmd = util.format('vm image list --json').split(' ');
        testUtils.executeCommand(suite, retry, cmd, function(result) {
          result.exitStatus.should.equal(0);
          var imageList = JSON.parse(result.text);
          imageList.some(function(image) {
            if ((image.operatingSystemType || image.oSDiskConfiguration.operatingSystem).toLowerCase() === category.toLowerCase() && image.category.toLowerCase() === 'public') {
              process.env.VM_LINUX_IMAGE = image.name;
              return true;
            }
          });
          callBack(process.env.VM_LINUX_IMAGE);
        });
      }
    }

    //get name of a vnet
    function getVnet(status, callback) {
      var cmd;
      if (getVnet.vnetName) {
        callback(getVnet.vnetName, getVnet.affinityName);
      } else {
        cmd = util.format('network vnet list --json').split(' ');
        testUtils.executeCommand(suite, retry, cmd, function(result) {
          result.exitStatus.should.equal(0);
          var vnetName = JSON.parse(result.text);
          var found = vnetName.some(function(vnet) {
            if (vnet.state.toLowerCase() === status.toLowerCase() && vnet.affinityGroup !== undefined) {
              getVnet.vnetName = vnet.name;
              getVnet.affinityName = vnet.affinityGroup;
              return true;
            }
          });

          if (!found) {
            getAffinityGroup(location, function(affinGrpName) {
              cmd = util.format('network vnet create %s -a %s --json', vnetName, affinGrpName).split(' ');
              testUtils.executeCommand(suite, retry, cmd, function(result) {
                result.exitStatus.should.equal(0);
                getVnet.vnetName = vnetName;
                getVnet.affinityName = affinGrpName;
                callback(getVnet.vnetName, getVnet.affinityName);
              });
            });
          } else {
            callback(getVnet.vnetName, getVnet.affinityName);
          }
        });
      }
    }

    // Get name of an image of the given category
    function getAffinityGroup(location, callBack) {
      var cmd;
      if (getAffinityGroup.affinGrpName) {
        callBack(getAffinityGroup.affinGrpName);
      } else {
        cmd = util.format('account affinity-group list --json').split(' ');
        testUtils.executeCommand(suite, retry, cmd, function(result) {
          result.exitStatus.should.equal(0);
          var affinList = JSON.parse(result.text);
          var found = affinList.some(function(affinGrp) {
            if (affinGrp.location === location) {
              getAffinityGroup.affinGrpName = affinGrp.name;
              return true;
            }
          });
          if (!found) {
            cmd = util.format('account affinity-group create -l %s -e %s -d %s %s --json',
              location, affinLabel, affinDesc, affinityName).split(' ');
            testUtils.executeCommand(suite, retry, cmd, function(result) {
              result.exitStatus.should.equal(0);
              getAffinityGroup.affinGrpName = affinityName;
              callBack(affinityName);
            });
          } else
            callBack(getAffinityGroup.affinGrpName);
        });
      }
    }
  });
});


text:
<?php
namespace App\Core\AuthN;

use App\Core\Session\SessionInterface;
use App\Models\User;

class AuthN
{
    /**
     * Name of the session variable for the user id.
     *
     * @var string
     */
    protected $session_id = 'user_id';

    /**
     * Name of the session variable for the user level.
     *
     * @var string
     */
    protected $session_level = 'user_level';

    /**
     * Session manager.
     *
     * @var SessionInterface
     */
    protected $session_manager;

    /**
     * AuthN constructor.
     *
     * @param SessionInterface $session_manager
     */
    public function __construct(SessionInterface $session_manager)
    {
        $this->session_manager = $session_manager;
    }

    /**
     * Get the currently logged in user's data.
     *
     * @return User|null
     */
    public function user()
    {
        return $this->isLoggedIn()
            ? User::find($this->session_manager->get($this->session_id))
            : null;
    }

    /**
     * Is there a user currently logged in?
     *
     * @return bool
     */
    public function isLoggedIn()
    {
        return (bool)$this->session_manager->get($this->session_id);
    }

    /**
     * Is the user at least a specified level?
     *
     * @param int $level
     * @return bool
     */
    public function isLevel($level)
    {
        return $this->isLoggedIn()
            && ($this->session_manager->get($this->session_level) >= $level);
    }

    /**
     * Attempt a user login with provided credentials.
     *
     * @param string $email
     * @param string $password
     * @return bool
     */
    public function attemptLogIn($email, $password)
    {
        if ($user = User::where('email', $email)->first()) {
            if (password_verify($password, $user->password)) {
                $this->session_manager->set($this->session_id, $user->id);
                $this->session_manager->set($this->session_level, $user->user_level);
                return true;
            }
        }
        return false;
    }

    /**
     * Log the user out.
     */
    public function logOut()
    {
        $this->session_manager->unset($this->session_id);
        $this->session_manager->unset($this->session_level);
    }
}


text:
'use babel';
import Bookmarks from './bookmarks';
import utils from './utils';

export default class BookmarksView {

    constructor(serializedState=[]) {

        // Create root element
        this.items = []
        this.element = document.createElement('div')
        this.element.setAttribute('class', 'bookmarks')

        // Create message element
        var title = document.createElement('h3')
        var content = document.createElement('ol')
        var actions = document.createElement('ol')

        title.textContent = 'Bookmarks'
        title.setAttribute('class', 'bookmarks-title')
        content.setAttribute('class', 'bookmarks-list list-tree')
        actions.setAttribute('class', 'bookmarks-panel-actions horizontal-list')

        this.elements = {
            title: title,
            content: content,
            actions: actions
        }

        for(key in this.elements) {
            this.element.appendChild(this.elements[key]);
        }

        window.bookmarkk = this;
        this.items = typeof serializedState === 'object' ? serializedState : []
        this.updateList();
    }

    addActionButton(options) {

        if(typeof options === 'undefined') options = {};

        var text = typeof options['text'] !== 'undefined' ? options.text : "";
        var cls = typeof options['icon'] !== 'undefined'
            ? ("icon icon-" + options.icon) : "";
        cls += typeof options['class'] !== 'undefined'
            ? (" btn " + options.class) : " btn";
        var elem = document.createElement('li');
        elem.setAttribute('class', cls);
        elem.textContent = text;
        this.elements.actions.appendChild(elem);
        return elem;

    }

    hasItem(item) {
        if( !item || !this.items.length ) return false
        return this.items.filter(obj => obj.path && obj.path == item.path).length > 0
    }

    getItem(item) {
        if(!item) return false
        for(key in this.items) {
            if(this.items[key].path==item.path)
                return item
        }
        return false
    }

    //
    // Adds a new list item into the bookmarks panel
    // Returns false if the item is already in the list.
    // Returns the item that was provided as an argument otherwise.
    // The returned item's "elements" member contains a list of inserted elements.
    //
    addItem(item, force=false) {

        if(this.hasItem(item) && force === false) return false;

        var element = document.createElement('li');
        var textElement = document.createElement('span');
        var closeElement = document.createElement('span');

        element.setAttribute('class', 'entry list-item');
        closeElement.setAttribute('class', 'close icon icon-cross');
        textElement.setAttribute('class', 'name icon icon-rocket');
        textElement.textContent = item.name;
        element.setAttribute('data-path', item.path);
        element.appendChild(textElement);
        element.appendChild(closeElement);

        item.elements = {
            root: element,
            open: textElement,
            close: closeElement
        }

        try {
            this.items.push(item)
        }
        catch(e) {
            console.log(e)
            this.items[item.name] = item
        }
        finally {
            this.updateList()
        }

        return item
    }

    removeItem(query) {
        if(typeof this.items[query]!=='undefined') {
            this.items[query].elements = null
            this.items.splice(key, 1)
        }
        else {
            for(key in this.items) {
                if(this.items[key].path==query) {
                    this.items[key].elements = null
                    this.items.splice(key, 1)
                    break
                }
            }
        }
        this.updateList();
    }

    updateList() {
        if(typeof this.items !== 'object') this.items = {};
        this.elements.content.innerHTML = "";
        for(key in this.items) {
            if (this.items[key] && this.items[key].elements) {
                var element = this.items[key].elements.root;
                this.elements.content.appendChild(element)
            }
        }
    }

    // Tear down any state and detach
    serialize() {
      return ([...(this.items || [])]).map(item => {
        let {path, name} = item
        return { path, name }
      })
    }

    // Tear down any state and detach
    destroy() {
        this.element.remove()
    }

    getElement() {
        return this.element
    }

}


text:
layout: post
category: cycling
title: My last cycling commute
date: 2016-04-28 09:52:51
---

It's a sad day. Today I rode to work for the last time. I still love bicycles. I
still love cycling. But I love *life* more.

### The beginning of the end

In my post [How do we stop this
happening?](http://johnsy.com/blog/2016/03/03/how-do-we-stop-this-happening/), I
mentioned the death of Alberto Paulon on Sydney Road, Brunswick. That was a
turning point for me. From that day I felt far more vulnerable on my bicycle
than ever before. The realisation that a cyclist's life could be wiped out in an
instant by somebody else's mistake hit me, and with each ride I would be paying
greater attention to hazards that could affect not just me, but those on bikes
around me. I became fearful for those who chose to ride without helmets or for
those who chose to listen to music as they rode. These choices may be good
choices in other environments, but not, as I see it, when cycling on the streets
of Melbourne.

And then came the day I was knocked off my bicycle by a passing motorist. To
recap...

I had been avoiding that stretch of Sydney Road, where Alberto was killed
because was and still is too dangerous for cyclists. I would often avoid the
parallel Upfield Bike Path at rush hour because it's just too busy and I got two
rear punctures in the week leading up to being knocked off my bike. Instead I
took a hook turn at Brunswick Road. The first motorist in the left hand lane
moved across as they passed me and knocked me clean off my bike as we crossed
Sydney Rd. Lots of people stopped to check I was okay, including the motorist,
who said, "I didn't see you".

I was wearing fluorescent yellow and the sun was beaming in the sky over
Brunswick.

Other than the shock and grazing to my upper body, I was OK but that incident
heightened my fears.

The motorist who hit me *must* have been distracted at the lights to not see a
cyclist fluorescent yellow pass in front of them as they were stopped at the
red light and to subsequently have been behind me so far across the junction
after the light had turned green.

From that day on, each time I have stopped at a junction, I have paid particular
attention to motorists at that junction to ensure that they have seen me.

*On every single commute, bar none, I have seen a motorist handling a
smartphone*.

Some days it's just one or two, but I have counted double digits on numerous
occasions and my commute is under 10km.

[It is illegal in all Australian states and territories to use a hand-held mobile phone while driving.](https://www.vicroads.vic.gov.au/safety-and-road-rules/driver-safety/mobile-phones-and-driving)

I have asked motorists to put down their phones on some commutes but I only ever
get abuse in return.

Cycling to and from work had ceased to be a pleasurable experience.

### The final straw

This morning, as I cycled alongside Princes Park, a grey Mazda 3 swerved into
the cycle lane ahead of me and crossed back and forth a few times. I caught the
car up in the inevitable traffic and the motorist was staring at their phone. I
gestured at them to put the phone down but I was invisible. How could I be
invisible to a motorist? I was wearing my typical fluorescent yellow cycling
jersey. I had flashing white and red lights atop my helmet. I had flashing white
and red lights attached to my bicycle. All the things my family and friends
recommend to me to "stay safe". I was wearing a helmet and my bike was
equipped with a bell and a reflector, as is required for my safety on the roads
in Victoria. And yet I was invisible to a motorist who was more interested in
the content served up by a smartphone screen than the direction of travel of
their vehicle. I passed this vehicle three times in traffic. Each time, the
driver was looking at their phone.

I had two other near-misses due to vehicles being in dedicated cycle lanes
between Royal Melbourne Hospital and the City Centre but by that point my mind
was made up.

## Will I return to cycling to work?

I would like to hope so, but I think it unlikely. There is a
["Towards Zero"](https://www.towardszero.vic.gov.au/) campaign running but
already in April
[twice as many cyclists have been killed on Victorian roads this year than in the whole of 2015](http://www.tac.vic.gov.au/road-safety/statistics/road-toll-year-to-date),
so it is not working.

I cannot see myself riding to work until the number of deaths on Melbourne's
streets is stable at zero.


text:
Ext.require([
    'OPF.prometheus.component.toolbar.ToolbarComponent',
    'OPF.prometheus.component.topmenu.TopMenuComponent',
    'OPF.prometheus.component.breadcrumbs.BreadcrumbsComponent',
    'OPF.prometheus.component.header.HeaderComponent',
    'OPF.prometheus.component.footer.FooterComponent',
    'OPF.prometheus.component.login.LoginComponent',
    'OPF.prometheus.component.forgotpassword.ForgotPasswordComponent',
    'OPF.prometheus.component.content.ContentComponent',
    'OPF.prometheus.component.action.ActionComponent',
    'OPF.prometheus.component.title.TitleComponent'
]);

Ext.define('OPF.prometheus.layout.BaseLayout', {
    extend: 'OPF.prometheus.layout.AbstractLayout',
    alias: 'widget.prometheus.layout.base',

    components: [],

    initComponent: function() {
        var topComponents = [];
        var bodyComponents = [];
        var footerComponents = [];

        Ext.each(this.components, function(component) {
            switch(component.area) {
                case 'top':
                    topComponents.push(component);
                    break;
                case 'body':
                    bodyComponents.push(component);
                    break;
                case 'footer':
                    footerComponents.push(component);
                    break;
            }
        });

        this.items = [
            {
                xtype: 'container',
                cls: 'top-container',
                hidden: topComponents.length == 0,
                items: topComponents
            },
            {
                xtype: 'container',
                cls: 'body-container',
                items: bodyComponents
            },
            {
                xtype: 'container',
                cls: 'footer',
                hidden: footerComponents.length == 0,
                items: footerComponents
            }
        ];

        this.callParent(arguments);
    }

});