text:
using System;
using NUnit.Framework;
using NServiceKit.Common.Extensions;
using NServiceKit.Logging;
using NServiceKit.Text;

namespace NServiceKit.Common.Tests.Models
{
    /// Queue of tasks.
	public class TaskQueue
	{
        /// The log.
		private static readonly ILog Log = LogManager.GetLogger(typeof(TaskQueue));

        /// The task load.
		public const string TaskLoad = "Load";

        /// Zero-based index of the task.
		public const string TaskIndex = "Index";

        /// The status pending.
		public const string StatusPending = "Pending";

        /// The status started.
		public const string StatusStarted = "Started";

        /// The status completed.
		public const string StatusCompleted = "Completed";

        /// The status failed.
		public const string StatusFailed = "Failed";

        /// The priority low.
		public const int PriorityLow = 0;

        /// The priority medium.
		public const int PriorityMedium = 1;

        /// The priority high.
		public const int PriorityHigh = 2;

        /// Gets or sets the identifier.
        /// <value>The identifier.</value>
		public int Id { get; set; }

        /// Gets or sets the identifier of the user.
        /// <value>The identifier of the user.</value>
		public Guid? UserId { get; set; }

        /// Gets or sets the task.
        /// <value>The task.</value>
		public string Task { get; set; }

        /// Gets or sets the content URN.
        /// <value>The content URN.</value>
		public string ContentUrn { get; set; }

        /// Gets or sets the status.
        /// <value>The status.</value>
		public string Status { get; set; }

        /// Gets or sets the created date.
        /// <value>The created date.</value>
		public DateTime CreatedDate { get; set; }

        /// Gets or sets the priority.
        /// <value>The priority.</value>
		public int Priority { get; set; }

        /// Gets or sets the no of attempts.
        /// <value>The no of attempts.</value>
		public int NoOfAttempts { get; set; }

        /// Gets or sets a message describing the error.
        /// <value>A message describing the error.</value>
		public string ErrorMessage { get; set; }

        /// Creates a new TaskQueue.
        /// <param name="id">The identifier.</param>
        /// <returns>A TaskQueue.</returns>
		public static TaskQueue Create(int id)
		{
			return new TaskQueue {
				ContentUrn = "urn:track:" + id,
				CreatedDate = DateTime.Now,
				Task = TaskLoad,
				Status = StatusPending,
				NoOfAttempts = 0,
			};
		}

        /// Assert is equal.
        /// <param name="actual">  The actual.</param>
        /// <param name="expected">The expected.</param>
		public static void AssertIsEqual(TaskQueue actual, TaskQueue expected)
		{
			Assert.That(actual.Id, Is.EqualTo(expected.Id));
			Assert.That(actual.UserId, Is.EqualTo(expected.UserId));
			Assert.That(actual.ContentUrn, Is.EqualTo(expected.ContentUrn));
			Assert.That(actual.Status, Is.EqualTo(expected.Status));
			try
			{
				Assert.That(actual.CreatedDate, Is.EqualTo(expected.CreatedDate));
			}
			catch (Exception ex)
			{
				Log.Error("Trouble with DateTime precisions, trying Assert again with rounding to seconds", ex);
				Assert.That(actual.CreatedDate.RoundToSecond(), Is.EqualTo(expected.CreatedDate.RoundToSecond()));
			}
			Assert.That(actual.Priority, Is.EqualTo(expected.Priority));
			Assert.That(actual.NoOfAttempts, Is.EqualTo(expected.NoOfAttempts));
			Assert.That(actual.ErrorMessage, Is.EqualTo(expected.ErrorMessage));
		}

	}
}


text:
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using Microsoft.CodeAnalysis.PersistentStorage;

namespace Microsoft.CodeAnalysis.Host
{
    internal interface IChecksummedPersistentStorageService : IPersistentStorageService2
    {
        new IChecksummedPersistentStorage GetStorage(Solution solution);
        new IChecksummedPersistentStorage GetStorage(Solution solution, bool checkBranchId);
        new IChecksummedPersistentStorage GetStorage(Workspace workspace, SolutionKey solutionKey, bool checkBranchId);
    }
}

redpajama_set_name: RedPajamaGithub


text:
TOP = ../../..
include $(TOP)/configure/CONFIG

DATA += $(patsubst ../%, %, $(wildcard ../*.edl))
DATA += $(patsubst ../%, %, $(wildcard ../*.gif))
DATA += $(patsubst ../%, %, $(wildcard ../*.png))
DATA += $(patsubst ../%, %, $(wildcard ../*.wrl))
DATA += $(patsubst ../%, %, $(wildcard ../*.wcfg))
#DATA += <name>.edl for "edl" files created with velocity scripts

include $(TOP)/configure/RULES

# How to specify a path for velocity dependencies
VELOCITYPATH = /home/diamond/R3.14.7/prod/support/pss/4-11/pssApp/opi/velocity

 %.edl: ../%.v
	(cd ..; velocity -p$(VELOCITYPATH) -l O.Common/velocity.log -a $(notdir $<)) > $@


text:
<?php

namespace DzAssetModule\Session;

/**
 * Aide pour les espaces de noms dans la session.
 *
 * Un espace de nom est un noeud de type array() dans $_SESSION.
 *
 * @category Source
 * @package  DzAssetModule\Session
 * @author   Adrien Desfourneaux (aka Dieze) <dieze51@gmail.com>
 * @license  http://www.apache.org/licenses/LICENSE-2.0  Apache License Version 2.0
 * @link     https://github.com/dieze/DzAssetModule
 */
class NamespaceHelper
{
    /**
     * Cré un espace de nom dans la session.
     *
     * Une liste de paramètres dynamique permet d'ajouter
     * une infinité de sous-namespaces de l'espace de nom
     * racine.
     *
     * @param string $namespace Espace de nom racine.
     *
     * @return void
     */
    public static function create($namespace)
    {
        $namespaces = func_get_args();
        $namespacesBefore = array();

        $current = &$_SESSION;
        foreach($namespaces as $namespace) {
            static::createSub($current, $namespace, $namespacesBefore);
            $current = &$current[$namespace];
            $namespacesBefore[] = $namespace;
        }
    }

    /**
     * Cré un sous-namespace dans le tableau passé en argument.
     *
     * @param array  &$current         Référence vers le tableau de l'espace de nom.
     * @param string $namespace        Nouvel espace de nom.
     * @param array  $namespacesBefore Espaces de noms pères. Nécessaire pour afficher un message d'erreur.
     *
     * @return void
     */
    protected static function createSub(&$current, $namespace, $namespacesBefore = null)
    {
        if (!isset($current[$namespace])) {
            $current[$namespace] = array();
        } elseif (!is_array($current[$namespace])) {
            $namespaces = array_merge((array)$namespacesBefore, (array)$namespace);

            throw new \Exception(static::buildSessionString($namespaces) . ' ne peut être utilisé comme espace de nom par SessionManager car il contient une valeur.');
        }
    }

    /**
     * Construit une chaine représentant la variable d'accès à
     * une variable de session en utilisant les clés spécifiés.
     *
     * @param array $keys Clés du tableau de session.
     *
     * @return string
     */
    protected static function buildSessionString($keys)
    {
        $result = '$_SESSION';

        foreach ($keys as $key) {
            $result .= '["' . $key . '"]';
        }

        return $result;
    }
}


text:
require "vagrant"

module VagrantPlugins
  module GuestSolaris11
    class Guest < Vagrant.plugin("2", :guest)
      def detect?(machine)
        machine.communicate.test("uname -s | grep SunOS")
      end
    end
  end
end


text:
require_relative 'dfareporting_utils'

def get_size(dfareporting, args)
  # Construct and execute the subaccount request
  result = dfareporting.sizes.list(
    :profileId => args[:profile_id],
    :height => args[:height],
    :width => args[:width]
  ).execute()

  result.data.sizes.each do |size|
    puts 'Found size with ID %d.' % size.id
  end
end

if __FILE__ == $0
  # Retrieve command line arguments
  args = DfaReportingUtils.get_arguments(ARGV, :profile_id, :height, :width)

  # Authenticate and initialize API service
  dfareporting = DfaReportingUtils.setup()

  get_size(dfareporting, args)
end


text: <link rel="stylesheet" type="text/css" href="http://cloud.github.com/downloads/lafeber/world-flags-sprite/flags32.css" />


text:
define(['./_isIndex'], function(isIndex) {

  /** Used as a safe reference for `undefined` in pre-ES5 environments. */
  var undefined;

  /**
   * The base implementation of `_.nth` which doesn't coerce arguments.
   *
   * @private
   * @param {Array} array The array to query.
   * @param {number} n The index of the element to return.
   * @returns {*} Returns the nth element of `array`.
   */
  function baseNth(array, n) {
    var length = array.length;
    if (!length) {
      return;
    }
    n += n < 0 ? length : 0;
    return isIndex(n, length) ? array[n] : undefined;
  }

  return baseNth;
});


text:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.IO;

namespace Orchard.Azure {
    /// <summary>
    /// THIS IS A HACK
    /// There is a bug in ASP.NET 4.0 in HttpEncoder.Current, which prevents some calls to HttpUtiliy.Decode/Encode
    /// from Application_Start, on IIS or Azure. This hack will be removed when the bug is corrected.
    /// This is fired by the assembly Microsoft.WindowsAzure.StorageClient. Should be corrected in .NET4 SP1
    /// </summary>
    public class HttpContextWeaver : IDisposable {
        private readonly HttpContext _current;

        public HttpContextWeaver()
        {
            _current = HttpContext.Current;
            HttpContext.Current = new HttpContext(new HttpRequest(String.Empty, "http://localhost", String.Empty), new HttpResponse(new StringWriter()));
        }

        public void Dispose() {
            HttpContext.Current = _current;
        }
    }
}


text:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:custom="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingBottom="4dp"
    android:paddingLeft="8dp"
    android:paddingRight="8dp"
    android:paddingTop="4dp"
    >

  <com.cesards.android.foregroundviews.ForegroundRelativeLayout
      android:id="@+id/relatives"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:layout_marginTop="8dp"
      android:background="@drawable/bg_card"
      custom:foreground="@drawable/fg_card"
      >

    <com.cesards.android.foregroundviews.ForegroundTextView
        android:id="@android:id/text1"
        style="@android:style/TextAppearance.Large"
        android:layout_width="match_parent"
        android:layout_height="?android:attr/actionBarSize"
        android:gravity="center"
        android:text="RelativeLayout List"
        />

  </com.cesards.android.foregroundviews.ForegroundRelativeLayout>
  >

  <com.cesards.android.foregroundviews.ForegroundLinearLayout
      android:id="@+id/linears"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:layout_marginTop="8dp"
      android:background="@drawable/bg_card"
      custom:foreground="@drawable/fg_card"
      >

    <TextView
        android:id="@android:id/text1"
        style="@android:style/TextAppearance.Large"
        android:layout_width="match_parent"
        android:layout_height="?android:attr/actionBarSize"
        android:gravity="center"
        android:text="LinearLayout List"
        />

  </com.cesards.android.foregroundviews.ForegroundLinearLayout>

  <com.cesards.android.foregroundviews.ForegroundTextView
      android:id="@+id/texts"
      style="@android:style/TextAppearance.Large"
      android:layout_width="match_parent"
      android:layout_height="?android:attr/actionBarSize"
      android:layout_marginTop="8dp"
      android:background="@drawable/bg_card"
      android:gravity="center"
      android:text="TextView List"
      custom:foreground="@drawable/fg_card"
      />

  <com.cesards.android.foregroundviews.ForegroundTextView
      android:id="@+id/images"
      style="@android:style/TextAppearance.Large"
      android:layout_width="match_parent"
      android:layout_height="?android:attr/actionBarSize"
      android:layout_marginTop="8dp"
      android:background="@drawable/bg_card"
      android:gravity="center"
      android:text="ImageView List"
      custom:foreground="@drawable/fg_card"
      />

</LinearLayout>


text:
"""
    tempserver.server
    ~~~~~~~~~~~~~~~~~

    This module provides the server for recieving and sending messages
    over the CAN Bus.

    The recieving server writes the value in a file, so that the Pi can read it
    from there.

    The sending server reads the value from the file in which the Pi's
    sensor the temperature writes, and broadcasts it via a CAN Bus.

    :copyright: (c) 2014 by Peter Justin.
    :license: BSD, see LICENSE for more details.
"""
import os
import sys
import time
import argparse
from datetime import datetime

import can

from reciever import recieve_temperature
from sender import send_temperature

def run_server(callback, **kwargs):
    """Calls a callback with its kwargs."""
    try:
        while True:
            callback(**kwargs)
            time.sleep(1)

    except KeyboardInterrupt:
        bus.shutdown()

if __name__ == "__main__":

    parser = argparse.ArgumentParser(
        description="Sends or recieves messages from a CAN Bus."
    )

    parser.add_argument('-t', '--type',
        help=("The server type. '--type send' sends the message and "
              "'--type recieve' recieves the message"),
        default="send"
    )

    parser.add_argument('-p', '--path',
        help=("The full path path to the file which should contain/recieve "
              "the temperature"),
        required=True,
    )

    parser.add_argument('-c', '--channel',
        help=("The name of the CAN channel. For example, such a channel could "
              "be named 'vcan0'. If not provided, it defaults back to the "
              "channel which is defined in the can.conf/ini"),
    )

    results = parser.parse_args()

    # We need the file on both sides because we need to read from the sensor on
    # the first Pi which stores the value in a file (?) and the other Pi reads
    # this value from a file (?). I'm not certain if this is actually the case.
    if not os.path.exists(results.path):
        parser.print_help(sys.stderr)
        parser.exit(2, "Path does not exist. Please enter a valid path/file.\n")

    if results.channel is not None:
        channel = results.channel
    else:
        channel = can.rc["channel"]

    bus = can.interface.Bus(channel)

    date = datetime.now().strftime("%d. %B %Y - %Mmin %Ssec")

    # sender
    if results.type == "send":
        print("Sender started on {}".format(date))

        run_server(send_temperature, bus=bus, input_file=results.path)

    # reciever
    elif results.type == "recieve":
        print("Reciever started on {}".format(date))

        run_server(recieve_temperature, bus=bus, output_file=results.path)

    # nothing - abort
    else:
        parser.print_help(sys.stderr)
        parser.exit(2, "{} is not a correct type.\n".format(results.type))


text:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="@dimen/nav_header_height"
              android:background="@drawable/header"
              android:gravity="bottom"
              android:orientation="vertical"
              android:paddingBottom="@dimen/activity_vertical_margin"
              android:paddingLeft="@dimen/activity_horizontal_margin"
              android:paddingRight="@dimen/activity_horizontal_margin"
              android:paddingTop="@dimen/activity_vertical_margin"
              android:theme="@style/ThemeOverlay.AppCompat.Dark">

  <ImageView
    android:id="@+id/imageView"
    android:layout_width="112dp"
    android:layout_height="75dp"
    android:paddingTop="@dimen/nav_header_vertical_spacing"
    android:src="@mipmap/icon"/>

  <TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:paddingTop="@dimen/nav_header_vertical_spacing"
    android:text="@string/app_name"
    android:textAppearance="@style/TextAppearance.AppCompat.Body2"/>

  <TextView
    android:id="@+id/textView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/header_description"
    android:textAppearance="@style/TextAppearance.AppCompat.Body2"
    android:textColor="@color/colorPrimary"/>

</LinearLayout>


text: class Skroutz::Resources::Address < Skroutz::Resource; end


text:
package org.apache.wicket.ajax.form;

import org.apache.wicket.Application;
import org.apache.wicket.Component;
import org.apache.wicket.WicketRuntimeException;
import org.apache.wicket.ajax.AjaxEventBehavior;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.attributes.AjaxRequestAttributes;
import org.apache.wicket.ajax.attributes.AjaxRequestAttributes.Method;
import org.apache.wicket.markup.html.form.FormComponent;
import org.apache.wicket.markup.html.form.validation.IFormValidator;
import org.apache.wicket.util.lang.Args;
import org.danekja.java.util.function.serializable.SerializableBiConsumer;
import org.danekja.java.util.function.serializable.SerializableConsumer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A behavior that updates the hosting FormComponent via ajax when an event it is attached to is
 * triggered. This behavior encapsulates the entire form-processing workflow as relevant only to
 * this component so if validation is successful the component's model will be updated according to
 * the submitted value.
 *

 * NOTE: This behavior does not validate any {@link IFormValidator}s attached to this form even
 * though they may reference the component being updated.
 *

 * NOTE: This behavior does not work on Choices or Groups use the
 * {@link AjaxFormChoiceComponentUpdatingBehavior} for that.
 *
 * @since 1.2
 *
 * @author Igor Vaynberg (ivaynberg)
 * @see #onUpdate(org.apache.wicket.ajax.AjaxRequestTarget)
 * @see #onError(org.apache.wicket.ajax.AjaxRequestTarget, RuntimeException)
 */
public abstract class AjaxFormComponentUpdatingBehavior extends AjaxEventBehavior
{
	private static final Logger log = LoggerFactory
		.getLogger(AjaxFormComponentUpdatingBehavior.class);

	/**
	 *
	 */
	private static final long serialVersionUID = 1L;

	/**
	 * Construct.
	 *
	 * @param event
	 *            event to trigger this behavior
	 */
	public AjaxFormComponentUpdatingBehavior(final String event)
	{
		super(event);
	}

	/**
	 *
	 * @see org.apache.wicket.behavior.AbstractAjaxBehavior#onBind()
	 */
	@Override
	protected void onBind()
	{
		super.onBind();

		Component component = getComponent();
		if (!(component instanceof FormComponent))
		{
			throw new WicketRuntimeException("Behavior " + getClass().getName()
				+ " can only be added to an instance of a FormComponent");
		}

		checkComponent((FormComponent<?>)component);
	}

	/**
	 * Check the component this behavior is bound to.
	 *

	 * Logs a warning in development mode when an {@link AjaxFormChoiceComponentUpdatingBehavior}
	 * should be used.
	 *
	 * @param component
	 *            bound component
	 */
	protected void checkComponent(FormComponent<?> component)
	{
		if (Application.get().usesDevelopmentConfig()
			&& AjaxFormChoiceComponentUpdatingBehavior.appliesTo(component))
		{
			log.warn(String
				.format(
					"AjaxFormComponentUpdatingBehavior is not supposed to be added in the form component at path: \"%s\". "
						+ "Use the AjaxFormChoiceComponentUpdatingBehavior instead, that is meant for choices/groups that are not one component in the html but many",
					component.getPageRelativePath()));
		}
	}

	/**
	 *
	 * @return FormComponent
	 */
	protected final FormComponent<?> getFormComponent()
	{
		return (FormComponent<?>)getComponent();
	}

	@Override
	protected void updateAjaxAttributes(AjaxRequestAttributes attributes)
	{
		super.updateAjaxAttributes(attributes);

		attributes.setMethod(Method.POST);
	}

	/**
	 *
	 * @see org.apache.wicket.ajax.AjaxEventBehavior#onEvent(org.apache.wicket.ajax.AjaxRequestTarget)
	 */
	@Override
	protected final void onEvent(final AjaxRequestTarget target)
	{
		final FormComponent<?> formComponent = getFormComponent();

		if ("blur".equals(getEvent().toLowerCase()) && disableFocusOnBlur())
		{
			target.focusComponent(null);
		}

		try
		{
			formComponent.inputChanged();
			formComponent.validate();
			if (formComponent.isValid())
			{
				if (getUpdateModel())
				{
					formComponent.valid();
					formComponent.updateModel();
				}

				onUpdate(target);
			}
			else
			{
				formComponent.invalid();

				onError(target, null);
			}
		}
		catch (RuntimeException e)
		{
			onError(target, e);
		}
		formComponent.updateAutoLabels(target);
	}

	/**
	 * Gives the control to the application to decide whether the form component model should
	 * be updated automatically or not. Make sure to call {@link org.apache.wicket.markup.html.form.FormComponent#valid()}
	 * additionally in case the application want to update the model manually.
	 *
	 * @return true if the model of form component should be updated, false otherwise
	 */
	protected boolean getUpdateModel()
	{
		return true;
	}

	/**
	 * Determines whether the focus will not be restored when the event is blur. By default this is
	 * true, as we don't want to re-focus component on blur event.
	 *
	 * @return true if refocusing should be disabled, false otherwise
	 */
	protected boolean disableFocusOnBlur()
	{
		return true;
	}

	/**
	 * Listener invoked on the ajax request. This listener is invoked after the component's model
	 * has been updated.
	 *
	 * @param target
	 *            the current request handler
	 */
	protected abstract void onUpdate(AjaxRequestTarget target);

	/**
	 * Called to handle any error resulting from updating form component. Errors thrown from
	 * {@link #onUpdate(org.apache.wicket.ajax.AjaxRequestTarget)} will not be caught here.
	 *
	 * The RuntimeException will be null if it was just a validation or conversion error of the
	 * FormComponent
	 *
	 * @param target
	 *            the current request handler
	 * @param e
	 *            the error that occurred during the update of the component
	 */
	protected void onError(AjaxRequestTarget target, RuntimeException e)
	{
		if (e != null)
		{
			throw e;
		}
	}

	/**
	 * Creates an {@link AjaxFormComponentUpdatingBehavior} based on lambda expressions
	 *
	 * @param eventName
	 *            the event name
	 * @param onUpdate
	 *            the {@code SerializableConsumer} which accepts the {@link AjaxRequestTarget}
	 * @return the {@link AjaxFormComponentUpdatingBehavior}
	 */
	public static AjaxFormComponentUpdatingBehavior onUpdate(String eventName,
		SerializableConsumer<AjaxRequestTarget> onUpdate)
	{
		Args.notNull(onUpdate, "onUpdate");

		return new AjaxFormComponentUpdatingBehavior(eventName)
		{
			private static final long serialVersionUID = 1L;

			@Override
			protected void onUpdate(AjaxRequestTarget target)
			{
				onUpdate.accept(target);
			}
		};
	}

	/**
	 * Creates an {@link AjaxFormComponentUpdatingBehavior} based on lambda expressions
	 *
	 * @param eventName
	 *            the event name
	 * @param onUpdate
	 *            the {@code SerializableConsumer} which accepts the {@link AjaxRequestTarget}
	 * @param onError
	 *            the {@code SerializableBiConsumer} which accepts the {@link AjaxRequestTarget} and
	 *            the {@link RuntimeException}
	 * @return the {@link AjaxFormComponentUpdatingBehavior}
	 */
	public static AjaxFormComponentUpdatingBehavior onUpdate(String eventName,
		SerializableConsumer<AjaxRequestTarget> onUpdate,
		SerializableBiConsumer<AjaxRequestTarget, RuntimeException> onError)
	{
		Args.notNull(onUpdate, "onUpdate");
		Args.notNull(onError, "onError");

		return new AjaxFormComponentUpdatingBehavior(eventName)
		{
			private static final long serialVersionUID = 1L;

			@Override
			protected void onUpdate(AjaxRequestTarget target)
			{
				onUpdate.accept(target);
			}

			@Override
			protected void onError(AjaxRequestTarget target, RuntimeException e)
			{
				onError.accept(target, e);
			}
		};
	}
}


text:
{{<layout}}

{{$pageTitle}}
Performance platform
{{/pageTitle}}

{{$content}}

Welcome to GOV.UK

Your account

Change your email or passphrase

Sign out

Your applications

	                Performance Platform admin

	                Administer the Performance Platform

	                •
	                Roles: Signin and Dashboard-editor

	                Support

	                Wraps Zendesk API

{{/content}}

{{/layout}}


text:
lessonmanager
=============


text:
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/child/notifications/notification_manager.h"

#include <utility>

#include "base/lazy_instance.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/utf_string_conversions.h"
#include "base/thread_task_runner_handle.h"
#include "base/threading/thread_local.h"
#include "content/child/notifications/notification_data_conversions.h"
#include "content/child/notifications/notification_dispatcher.h"
#include "content/child/service_worker/web_service_worker_registration_impl.h"
#include "content/child/thread_safe_sender.h"
#include "content/common/notification_constants.h"
#include "content/public/common/notification_resources.h"
#include "content/public/common/platform_notification_data.h"
#include "third_party/WebKit/public/platform/URLConversion.h"
#include "third_party/WebKit/public/platform/WebSecurityOrigin.h"
#include "third_party/WebKit/public/platform/modules/notifications/WebNotificationDelegate.h"

using blink::WebNotificationPermission;

namespace content {
namespace {

int CurrentWorkerId() {
  return WorkerThread::GetCurrentId();
}

// Checks whether |notification_data| specifies any non-empty resources that
// need to be fetched.
bool HasResourcesToFetch(const blink::WebNotificationData& notification_data) {
  if (!notification_data.icon.isEmpty())
    return true;
  for (const auto& action : notification_data.actions) {
    if (!action.icon.isEmpty())
      return true;
  }
  return false;
}

}  // namespace

static base::LazyInstance<base::ThreadLocalPointer<NotificationManager>>::Leaky
    g_notification_manager_tls = LAZY_INSTANCE_INITIALIZER;

NotificationManager::NotificationManager(
    ThreadSafeSender* thread_safe_sender,
    base::SingleThreadTaskRunner* main_thread_task_runner,
    NotificationDispatcher* notification_dispatcher)
    : thread_safe_sender_(thread_safe_sender),
      notification_dispatcher_(notification_dispatcher),
      notifications_tracker_(main_thread_task_runner) {
  g_notification_manager_tls.Pointer()->Set(this);
}

NotificationManager::~NotificationManager() {
  g_notification_manager_tls.Pointer()->Set(nullptr);
}

NotificationManager* NotificationManager::ThreadSpecificInstance(
    ThreadSafeSender* thread_safe_sender,
    base::SingleThreadTaskRunner* main_thread_task_runner,
    NotificationDispatcher* notification_dispatcher) {
  if (g_notification_manager_tls.Pointer()->Get())
    return g_notification_manager_tls.Pointer()->Get();

  NotificationManager* manager = new NotificationManager(
      thread_safe_sender, main_thread_task_runner, notification_dispatcher);
  if (CurrentWorkerId())
    WorkerThread::AddObserver(manager);
  return manager;
}

void NotificationManager::WillStopCurrentWorkerThread() {
  delete this;
}

void NotificationManager::show(
    const blink::WebSecurityOrigin& origin,
    const blink::WebNotificationData& notification_data,
    blink::WebNotificationDelegate* delegate) {
  DCHECK_EQ(0u, notification_data.actions.size());

  if (!HasResourcesToFetch(notification_data)) {
    DisplayPageNotification(origin, notification_data, delegate,
                            NotificationResources());
    return;
  }

  notifications_tracker_.FetchResources(
      notification_data, delegate,
      base::Bind(&NotificationManager::DisplayPageNotification,
                 base::Unretained(this),  // this owns |notifications_tracker_|
                 origin, notification_data, delegate));
}

void NotificationManager::showPersistent(
    const blink::WebSecurityOrigin& origin,
    const blink::WebNotificationData& notification_data,
    blink::WebServiceWorkerRegistration* service_worker_registration,
    blink::WebNotificationShowCallbacks* callbacks) {
  DCHECK(service_worker_registration);

  int64_t service_worker_registration_id =
      static_cast<WebServiceWorkerRegistrationImpl*>(
          service_worker_registration)
          ->registration_id();

  scoped_ptr<blink::WebNotificationShowCallbacks> owned_callbacks(callbacks);

  // Verify that the author-provided payload size does not exceed our limit.
  // This is an implementation-defined limit to prevent abuse of notification
  // data as a storage mechanism. A UMA histogram records the requested sizes,
  // which enables us to track how much data authors are attempting to store.
  //
  // If the size exceeds this limit, reject the showNotification() promise. This
  // is outside of the boundaries set by the specification, but it gives authors
  // an indication that something has gone wrong.
  size_t author_data_size = notification_data.data.size();

  UMA_HISTOGRAM_COUNTS_1000("Notifications.AuthorDataSize", author_data_size);

  if (author_data_size > PlatformNotificationData::kMaximumDeveloperDataSize) {
    owned_callbacks->onError();
    return;
  }

  if (!HasResourcesToFetch(notification_data)) {
    NotificationResources notification_resources;

    // Action indices are expected to have a corresponding icon bitmap, which
    // may be empty when the developer provided no (or an invalid) icon.
    if (!notification_data.actions.isEmpty()) {
      notification_resources.action_icons.resize(
          notification_data.actions.size());
    }

    DisplayPersistentNotification(
        origin, notification_data, service_worker_registration_id,
        std::move(owned_callbacks), notification_resources);
    return;
  }

  notifications_tracker_.FetchResources(
      notification_data, nullptr /* delegate */,
      base::Bind(&NotificationManager::DisplayPersistentNotification,
                 base::Unretained(this),  // this owns |notifications_tracker_|
                 origin, notification_data, service_worker_registration_id,
                 base::Passed(&owned_callbacks)));
}

void NotificationManager::getNotifications(
    const blink::WebString& filter_tag,
    blink::WebServiceWorkerRegistration* service_worker_registration,
    blink::WebNotificationGetCallbacks* callbacks) {
  DCHECK(service_worker_registration);
  DCHECK(callbacks);

  WebServiceWorkerRegistrationImpl* service_worker_registration_impl =
      static_cast<WebServiceWorkerRegistrationImpl*>(
          service_worker_registration);

  GURL origin = GURL(service_worker_registration_impl->scope()).GetOrigin();
  int64_t service_worker_registration_id =
      service_worker_registration_impl->registration_id();

  // TODO(peter): GenerateNotificationId is more of a request id. Consider
  // renaming the method in the NotificationDispatcher if this makes sense.
  int request_id =
      notification_dispatcher_->GenerateNotificationId(CurrentWorkerId());

  pending_get_notification_requests_.AddWithID(callbacks, request_id);

  thread_safe_sender_->Send(new PlatformNotificationHostMsg_GetNotifications(
      request_id, service_worker_registration_id, origin,
      base::UTF16ToUTF8(base::StringPiece16(filter_tag))));
}

void NotificationManager::close(blink::WebNotificationDelegate* delegate) {
  if (notifications_tracker_.CancelResourceFetches(delegate))
    return;

  for (auto& iter : active_page_notifications_) {
    if (iter.second != delegate)
      continue;

    thread_safe_sender_->Send(
        new PlatformNotificationHostMsg_Close(iter.first));
    active_page_notifications_.erase(iter.first);
    return;
  }

  // It should not be possible for Blink to call close() on a Notification which
  // does not exist in either the pending or active notification lists.
  NOTREACHED();
}

void NotificationManager::closePersistent(
    const blink::WebSecurityOrigin& origin,
    int64_t persistent_notification_id) {
  thread_safe_sender_->Send(new PlatformNotificationHostMsg_ClosePersistent(
      // TODO(mkwst): This is potentially doing the wrong thing with unique
      // origins. Perhaps also 'file:', 'blob:' and 'filesystem:'. See
      // https://crbug.com/490074 for detail.
      blink::WebStringToGURL(origin.toString()), persistent_notification_id));
}

void NotificationManager::notifyDelegateDestroyed(
    blink::WebNotificationDelegate* delegate) {
  if (notifications_tracker_.CancelResourceFetches(delegate))
    return;

  for (auto& iter : active_page_notifications_) {
    if (iter.second != delegate)
      continue;

    active_page_notifications_.erase(iter.first);
    return;
  }
}

WebNotificationPermission NotificationManager::checkPermission(
    const blink::WebSecurityOrigin& origin) {
  WebNotificationPermission permission =
      blink::WebNotificationPermissionAllowed;
  // TODO(mkwst): This is potentially doing the wrong thing with unique
  // origins. Perhaps also 'file:', 'blob:' and 'filesystem:'. See
  // https://crbug.com/490074 for detail.
  thread_safe_sender_->Send(new PlatformNotificationHostMsg_CheckPermission(
      blink::WebStringToGURL(origin.toString()), &permission));

  return permission;
}

size_t NotificationManager::maxActions() {
  return kPlatformNotificationMaxActions;
}

bool NotificationManager::OnMessageReceived(const IPC::Message& message) {
  bool handled = true;
  IPC_BEGIN_MESSAGE_MAP(NotificationManager, message)
    IPC_MESSAGE_HANDLER(PlatformNotificationMsg_DidShow, OnDidShow);
    IPC_MESSAGE_HANDLER(PlatformNotificationMsg_DidShowPersistent,
                        OnDidShowPersistent)
    IPC_MESSAGE_HANDLER(PlatformNotificationMsg_DidClose, OnDidClose);
    IPC_MESSAGE_HANDLER(PlatformNotificationMsg_DidClick, OnDidClick);
    IPC_MESSAGE_HANDLER(PlatformNotificationMsg_DidGetNotifications,
                        OnDidGetNotifications)
    IPC_MESSAGE_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP()

  return handled;
}

void NotificationManager::OnDidShow(int notification_id) {
  const auto& iter = active_page_notifications_.find(notification_id);
  if (iter == active_page_notifications_.end())
    return;

  iter->second->dispatchShowEvent();
}

void NotificationManager::OnDidShowPersistent(int request_id, bool success) {
  blink::WebNotificationShowCallbacks* callbacks =
      pending_show_notification_requests_.Lookup(request_id);
  DCHECK(callbacks);

  if (!callbacks)
    return;

  if (success)
    callbacks->onSuccess();
  else
    callbacks->onError();

  pending_show_notification_requests_.Remove(request_id);
}

void NotificationManager::OnDidClose(int notification_id) {
  const auto& iter = active_page_notifications_.find(notification_id);
  if (iter == active_page_notifications_.end())
    return;

  iter->second->dispatchCloseEvent();
  active_page_notifications_.erase(iter);
}

void NotificationManager::OnDidClick(int notification_id) {
  const auto& iter = active_page_notifications_.find(notification_id);
  if (iter == active_page_notifications_.end())
    return;

  iter->second->dispatchClickEvent();
}

void NotificationManager::OnDidGetNotifications(
    int request_id,
    const std::vector<PersistentNotificationInfo>& notification_infos) {
  blink::WebNotificationGetCallbacks* callbacks =
      pending_get_notification_requests_.Lookup(request_id);
  DCHECK(callbacks);
  if (!callbacks)
    return;

  blink::WebVector<blink::WebPersistentNotificationInfo> notifications(
      notification_infos.size());

  for (size_t i = 0; i < notification_infos.size(); ++i) {
    blink::WebPersistentNotificationInfo web_notification_info;
    web_notification_info.persistentId = notification_infos[i].first;
    web_notification_info.data =
        ToWebNotificationData(notification_infos[i].second);

    notifications[i] = web_notification_info;
  }

  callbacks->onSuccess(notifications);

  pending_get_notification_requests_.Remove(request_id);
}

void NotificationManager::DisplayPageNotification(
    const blink::WebSecurityOrigin& origin,
    const blink::WebNotificationData& notification_data,
    blink::WebNotificationDelegate* delegate,
    const NotificationResources& notification_resources) {
  DCHECK_EQ(0u, notification_data.actions.size());
  DCHECK_EQ(0u, notification_resources.action_icons.size());

  int notification_id =
      notification_dispatcher_->GenerateNotificationId(CurrentWorkerId());

  active_page_notifications_[notification_id] = delegate;
  // TODO(mkwst): This is potentially doing the wrong thing with unique
  // origins. Perhaps also 'file:', 'blob:' and 'filesystem:'. See
  // https://crbug.com/490074 for detail.
  thread_safe_sender_->Send(new PlatformNotificationHostMsg_Show(
      notification_id, blink::WebStringToGURL(origin.toString()),
      ToPlatformNotificationData(notification_data), notification_resources));
}

void NotificationManager::DisplayPersistentNotification(
    const blink::WebSecurityOrigin& origin,
    const blink::WebNotificationData& notification_data,
    int64_t service_worker_registration_id,
    scoped_ptr<blink::WebNotificationShowCallbacks> callbacks,
    const NotificationResources& notification_resources) {
  DCHECK_EQ(notification_data.actions.size(),
            notification_resources.action_icons.size());

  // TODO(peter): GenerateNotificationId is more of a request id. Consider
  // renaming the method in the NotificationDispatcher if this makes sense.
  int request_id =
      notification_dispatcher_->GenerateNotificationId(CurrentWorkerId());

  pending_show_notification_requests_.AddWithID(callbacks.release(),
                                                request_id);

  // TODO(mkwst): This is potentially doing the wrong thing with unique
  // origins. Perhaps also 'file:', 'blob:' and 'filesystem:'. See
  // https://crbug.com/490074 for detail.
  thread_safe_sender_->Send(new PlatformNotificationHostMsg_ShowPersistent(
      request_id, service_worker_registration_id,
      blink::WebStringToGURL(origin.toString()),
      ToPlatformNotificationData(notification_data), notification_resources));
}

}  // namespace content


text:
Kwf.namespace('Kwf.EyeCandy.Lightbox');

$(document).on('click', 'a[data-kwc-lightbox]', function(event) {
    var el = event.currentTarget;
    var $el = $(el);
    var options = $el.data('kwc-lightbox');
    if (Kwf.EyeCandy.Lightbox.allByUrl[$el.attr('href')]) {
        l = Kwf.EyeCandy.Lightbox.allByUrl[$el.attr('href')];
    } else {
        l = new Kwf.EyeCandy.Lightbox.Lightbox($el.attr('href'), options);
    }
    el.kwfLightbox = l;

    if (Kwf.EyeCandy.Lightbox.currentOpen &&
        Kwf.EyeCandy.Lightbox.currentOpen.href == $el.attr('href')
    ) {
        //already open, ignore click
        event.preventDefault();
        return;
    }
    this.kwfLightbox.show({
        clickTarget: this
    });
    Kwf.Utils.HistoryState.currentState.lightbox = this.href;
    Kwf.Utils.HistoryState.pushState(document.title, this.href);

    event.preventDefault();
});

Kwf.onJElementReady('.kwfLightbox', function lightboxEl(el) {
    //initialize lightbox that was not dynamically created (created by ContentSender/Lightbox)
    if (el[0].kwfLightbox) return;
    var options = jQuery.parseJSON(el.find('input.options').val());
    var l = new Kwf.EyeCandy.Lightbox.Lightbox(window.location.href, options);
    Kwf.Utils.HistoryState.currentState.lightbox = window.location.href;
    Kwf.Utils.HistoryState.updateState();
    l.lightboxEl = el;
    l.innerLightboxEl = el.find('.kwfLightboxInner');
    l.fetched = true;
    l.initialize();
    l.closeHref = window.location.href.substr(0, window.location.href.lastIndexOf('/'));
    l.contentEl = l.innerLightboxEl.find('.kwfLightboxContent');
    l.style.afterCreateLightboxEl();
    l.style.onShow();
    l.style.onContentReady();
    el[0].kwfLightbox = l;
    Kwf.EyeCandy.Lightbox.currentOpen = l;

    //callOnContentReady so eg. ResponsiveEl can do it's job based on the new with of the lightbox
    Kwf.callOnContentReady(l.contentEl, {action: 'show'});
}, { priority: 10 }); //after ResponsiveEl so lightbox can adapt to responsive content

Kwf.onContentReady(function lightboxContent(readyEl, options)
{
    if (!Kwf.EyeCandy.Lightbox.currentOpen) return;

    readyEl = $(readyEl);
    if (readyEl.is(':visible')) {
        //callOnContentReady was called for an element inside the lightbox, style can update the lightbox size
        if (Kwf.EyeCandy.Lightbox.currentOpen.lightboxEl
            && Kwf.EyeCandy.Lightbox.currentOpen.lightboxEl.is(':visible')
            && ($.contains(Kwf.EyeCandy.Lightbox.currentOpen.innerLightboxEl, readyEl)
            || $.contains(readyEl, Kwf.EyeCandy.Lightbox.currentOpen.innerLightboxEl))
        ) {
            Kwf.EyeCandy.Lightbox.currentOpen.style.onContentReady();
        }
    }
});

Kwf.Utils.HistoryState.on('popstate', function() {
    if (Kwf.EyeCandy.Lightbox.onlyCloseOnPopstate) {
        //onlyCloseOnPopstate is set in closeAndPushState
        //if multiple lightboxes are in history and we close current one we go back in history until none is open
        //so just close current one and don't show others (required to avoid flicker on closing)
        if (Kwf.EyeCandy.Lightbox.currentOpen) {
            Kwf.EyeCandy.Lightbox.currentOpen.close();
        }
        return;
    }
    var lightbox = Kwf.Utils.HistoryState.currentState.lightbox;
    if (lightbox) {
        if (!Kwf.EyeCandy.Lightbox.allByUrl[lightbox]) return;
        if (Kwf.EyeCandy.Lightbox.currentOpen != Kwf.EyeCandy.Lightbox.allByUrl[lightbox]) {
            Kwf.EyeCandy.Lightbox.allByUrl[lightbox].show();
        }
    } else {
        if (Kwf.EyeCandy.Lightbox.currentOpen) {
            Kwf.EyeCandy.Lightbox.currentOpen.close();
        }
    }
});

if (!(Ext2.isMac && 'ontouchstart' in document.documentElement)) {
    var timer = 0;
    $(window).resize(function(ev) {
        clearTimeout(timer);
        timer = setTimeout(function(){
            if (Kwf.EyeCandy.Lightbox.currentOpen) {
                Kwf.EyeCandy.Lightbox.currentOpen.style.onResizeWindow(ev);
            }
        }, 100);
    });

} else {
    //on iOS listen to orientationchange as resize event triggers randomly when scrolling
    $(window).on('orientationchange', function(ev) {
        if (Kwf.EyeCandy.Lightbox.currentOpen) {
            Kwf.EyeCandy.Lightbox.currentOpen.style.onResizeWindow(ev);
        }
    });
}

Kwf.EyeCandy.Lightbox.currentOpen = null;
Kwf.EyeCandy.Lightbox.allByUrl = {};
Kwf.EyeCandy.Lightbox.Lightbox = function(href, options) {
    this.href = href;
    Kwf.EyeCandy.Lightbox.allByUrl[href] = this;
    this.options = options;
    if (options.style) {
        this.style = new Kwf.EyeCandy.Lightbox.Styles[options.style](this);
    } else {
        this.style = new Kwf.EyeCandy.Lightbox.Styles.CenterBox(this);
    }
};
Kwf.EyeCandy.Lightbox.Lightbox.prototype = {
    fetched: false,
    _blockOnContentReady: false,
    createLightboxEl: function()
    {
        if (this.lightboxEl) return;

        var cls = 'kwfLightbox';
        if (this.options.style) cls += ' kwfLightbox'+this.options.style;
        if (this.options.cssClass) cls += ' '+this.options.cssClass;
        var lightbox = $(
            '
'+
                '

'+
            '
'
        );
        $(document.body).append(lightbox);
        lightbox[0].kwfLightbox = this; //don't initialize again in onContentReady

        this.lightboxEl = lightbox;
        this.innerLightboxEl = lightbox.find('.kwfLightboxInner');
        var el = this.innerLightboxEl;

        if (this.options.width) {
            el.width(parseInt(this.options.width) /*+ el.getBorderWidth("lr") + el.getPadding("lr")*/);
        }
        if (this.options.height) {
            el.height(parseInt(this.options.height) /*+ el.getBorderWidth("tb") + el.getPadding("tb")*/);
        }
        if (this.options.adaptHeight) {
            this.lightboxEl.addClass('adaptHeight');
        }
        this.style.afterCreateLightboxEl();
        this.lightboxEl.hide();
    },
    fetchContent: function()
    {
        if (this.fetched) return;
        this.fetched = true;

        $.ajax({
            url: Kwf.getKwcRenderUrl(),
            data: { url: 'http://'+location.host+this.href },
            dataType: 'html',
            context: this
        }).done(function(responseText) {
            this.contentEl = $(
                '

'
            );
            this.closeButtonEl = $(
                ''
            );
            this.innerLightboxEl.append(this.contentEl);
            this.innerLightboxEl.append(this.closeButtonEl);

            this.style.updateContent(responseText);

            if (this.lightboxEl.is(':visible')) {
                this.contentEl.hide();
            }

            var self = this;
            var showContent = function() {
                self.innerLightboxEl.removeClass('kwfLightboxLoading');
                self.innerLightboxEl.find('.loading').remove();
                if (self.lightboxEl.is(':visible')) {
                    self.contentEl.fadeIn();
                }
                self.style.afterContentShown();
                if (self.lightboxEl.is(':visible')) {
                    self.preloadLinks();
                }
            };
            var imagesToLoad = 0;
            this.contentEl.find('img.hideWhileLoading').each(function() {
                imagesToLoad++;
                $(this).on('load', function() {
                    imagesToLoad--;
                    if (imagesToLoad <= 0) showContent.call(this);
                });
            });
            if (imagesToLoad == 0) showContent.call(this);

            this.initialize();
        }).fail(function() {
            //fallback
            location.href = this.href;
        });
    },
    show: function(options)
    {
        this.createLightboxEl();

        this.style.onShow(options);

        if (!this.closeHref) {
            if (Kwf.EyeCandy.Lightbox.currentOpen) {
                this.closeHref = Kwf.EyeCandy.Lightbox.currentOpen.closeHref;
            } else {
                this.closeHref = window.location.href;
            }
        }

        if (Kwf.EyeCandy.Lightbox.currentOpen) {
            var closeOptions = {};
            if (options && options.clickTarget) {
                closeOptions.showClickTarget = options.clickTarget;
            }
            Kwf.EyeCandy.Lightbox.currentOpen.close(closeOptions);
        }
        Kwf.EyeCandy.Lightbox.currentOpen = this;

        this.showOptions = options;

        this.lightboxEl.addClass('kwfLightboxOpen');
        if (this.fetched) {
            if (!this.lightboxEl.is(':visible')) {
                this.lightboxEl.show();
                Kwf.callOnContentReady(this.lightboxEl, {action: 'show'});
                this.style.afterContentShown();
                this.lightboxEl.hide();
                this.lightboxEl.fadeIn();
                this.preloadLinks();
            }
        } else {
            this.lightboxEl.show();
            this.fetchContent();
        }
        this.style.afterShow(options);

        Kwf.Statistics.count(this.href);
    },
    close: function(options) {
        this.lightboxEl.hide();
        //so eg. flash component can remove object
        Kwf.callOnContentReady(this.lightboxEl, {action: 'hide'});
        this.lightboxEl.show();

        this.style.onClose(options);
        this.lightboxEl.removeClass('kwfLightboxOpen');
        Kwf.EyeCandy.Lightbox.currentOpen = null;
    },
    closeAndPushState: function() {
        if (Kwf.Utils.HistoryState.entries > 0) {
            Kwf.EyeCandy.Lightbox.onlyCloseOnPopstate = true; //required to avoid flicker on closing, see popstate handler
            var previousEntries = Kwf.Utils.HistoryState.entries;
            history.back();
            var closeLightbox = (function() {
                //didn't change yet, wait a bit longer
                if (previousEntries == Kwf.Utils.HistoryState.entries) {
                    closeLightbox.defer(10, this);
                    return;
                }
                //check if there is still a lightbox open
                //has to be defered because closing happens in 'popstate' event which is async in IE
                if (Kwf.Utils.HistoryState.currentState.lightbox) {
                    previousEntries = Kwf.Utils.HistoryState.entries;
                    history.back();
                    closeLightbox.defer(1, this);
                } else {
                    //last entry in history that had lightbox open
                    Kwf.EyeCandy.Lightbox.onlyCloseOnPopstate = false;
                }
            });
            closeLightbox.defer(1, this);
        } else {
            delete Kwf.Utils.HistoryState.currentState.lightbox;
            Kwf.Utils.HistoryState.replaceState(document.title, this.closeHref);
            //location.replace(this.closeHref);
            this.close();
        }
    },
    initialize: function()
    {
        var closeButtons = this.innerLightboxEl.find('.closeButton');
        closeButtons.click((function(ev) {
            ev.preventDefault();
            this.closeAndPushState();
        }).bind(this));
    },
    preloadLinks: function() {
        this.innerLightboxEl.find('a.preload').each(function() {
            if (this.kwfLightbox) this.kwfLightbox.preload();
        }, this);
    },
    preload: function() {
        this.createLightboxEl();
        this.fetchContent();
    }
};

Kwf.EyeCandy.Lightbox.Styles = {};
Kwf.EyeCandy.Lightbox.Styles.Abstract = function(lightbox) {
    this.lightbox = lightbox;
    this.init();
};
Kwf.EyeCandy.Lightbox.Styles.Abstract.masks = 0;
Kwf.EyeCandy.Lightbox.Styles.Abstract.prototype = {
    init: function() {},
    afterCreateLightboxEl: function() {},
    afterContentShown: function() {},
    updateContent: function(responseText) {
        this.lightbox.contentEl.html(responseText);

        this._blockOnContentReady = true; //don't resize twice
        //callOnContentReady so eg. ResponsiveEl can do it's job which might change the height of contents
        Kwf.callOnContentReady(this.lightbox.contentEl, {action: 'render'});
        this._blockOnContentReady = false;
    },
    onShow: function() {},
    afterShow: function() {},
    onClose: function() {},
    afterClose: function() {},
    onContentReady: function() {},
    onResizeWindow: function() {},

    mask: function() {
        //calling mask multiple times in valid, unmask must be called exactly often
        Kwf.EyeCandy.Lightbox.Styles.Abstract.masks++;
        if (Kwf.EyeCandy.Lightbox.Styles.Abstract.masks > 1) return;
        $(document.body).addClass('kwfLightboxTheaterMode');
        var maskEl = $(document.body).find('.lightboxMask');
        if (maskEl.length) {
            maskEl.show();
        } else {
            maskEl = $(document.body).append('

');
            maskEl.click(function(ev) {
                if ($(document.body).find('.lightboxMask').is(ev.target)) {
                    if (Kwf.EyeCandy.Lightbox.currentOpen) {
                        Kwf.EyeCandy.Lightbox.currentOpen.style.onMaskClick();
                    }
                }
            });
        }
    },
    unmask: function() {
        Kwf.EyeCandy.Lightbox.Styles.Abstract.masks--;
        if (Kwf.EyeCandy.Lightbox.Styles.Abstract.masks > 0) return;
        $(document.body).find('.lightboxMask').fadeOut({
            complete: function() {
                $(document.body).removeClass('kwfLightboxTheaterMode');
                $(document.body).find('.lightboxMask').hide();
            }
        });
    },
    onMaskClick: function()
    {
        this.lightbox.closeAndPushState();
    }
};

Kwf.EyeCandy.Lightbox.Styles.CenterBox = Ext2.extend(Kwf.EyeCandy.Lightbox.Styles.Abstract, {
    init: function()
    {
        this._previousWindowWidth = $(window).width();
        this._previousWindowHeight = $(window).height();
    },

    afterCreateLightboxEl: function() {
        this.lightbox.lightboxEl.click((function(ev) {
            if (this.lightbox.lightboxEl.is(ev.target)) {
                this.lightbox.closeAndPushState();
            }
        }).bind(this));

        this._resizeContent();
    },
    _resizeContent: function()
    {
        this._updateMobile();

        //if content is larger than window, resize accordingly
        var originalWidth = this.lightbox.innerLightboxEl.width();
        var originalHeight = this.lightbox.innerLightboxEl.height();

        var maxSize = this._getMaxContentSize();

        if (originalWidth > maxSize.width) {
            var ratio = originalHeight / originalWidth;
            var offs = originalWidth-maxSize.width;
            originalWidth -= offs;
            if (this.lightbox.options.adaptHeight) originalHeight -= offs*ratio;
        }
        if (this.lightbox.options.adaptHeight && originalHeight > maxSize.height) {
            var ratio = originalWidth / originalHeight;
            var offs = originalHeight-maxSize.height;
            originalHeight -= offs;
            originalWidth -= offs*ratio;
        }
        if (!this.lightbox.options.adaptHeight && originalHeight > maxSize.height) {
            //delete originalHeight;
        }
        this.lightbox.innerLightboxEl.width(originalWidth);
        this.lightbox.innerLightboxEl.height(originalHeight);
        this._center(false);
    },
    afterContentShown: function() {

        //reset to initial size so lightbox can grow
        var initialSize = {
            width: null,
            height: null
        };
        if (this.lightbox.options.width) initialSize.width = this.lightbox.options.width;
        if (this.lightbox.options.height) initialSize.height = this.lightbox.options.height;
        this.lightbox.innerLightboxEl.css(initialSize);

        this._resizeContent();
        this._center(false);
    },
    _getOuterMargin: function()
    {
        var maxSize = this._getMaxContentSize(false);
        if (maxSize.width <= 650) {
            return 0;
        } else if (maxSize.width <= 1100) {
            return 20;
        } else if (maxSize.width <= 1600) {
            return 40;
        } else {
            return 60;
        }
    },
    _updateMobile: function()
    {
        if (this._getOuterMargin() == 0) {
            this.lightbox.lightboxEl.addClass('mobile');
        } else {
            this.lightbox.lightboxEl.removeClass('mobile');
        }
    },
    _getMaxContentSize: function(subtractOuterMargin) {
        this.lightbox.lightboxEl.css('overflow', 'hidden');
        var maxSize = {
            width: this.lightbox.lightboxEl.innerWidth(),
            height: this.lightbox.lightboxEl.innerHeight()
        };
        this.lightbox.lightboxEl.css('overflow', '');
        if (subtractOuterMargin !== false) {
            maxSize.width -= this._getOuterMargin()*2;
            maxSize.height -= this._getOuterMargin()*2;
        }
        maxSize.width -= parseInt(this.lightbox.innerLightboxEl.css('paddingLeft'))
                            + parseInt(this.lightbox.innerLightboxEl.css('paddingRight'));
        maxSize.height -= parseInt(this.lightbox.innerLightboxEl.css('paddingTop'))
                            + parseInt(this.lightbox.innerLightboxEl.css('paddingBottom'));

        return maxSize;
    },

    _getContentSize: function(dontDeleteHeight)
    {
        var newWidth = this.lightbox.contentEl.width();
        var newHeight = this.lightbox.contentEl.height();
        var maxSize = this._getMaxContentSize();
        if (newWidth > maxSize.width) newWidth = maxSize.width;

        if (this.lightbox.options.adaptHeight && newHeight > maxSize.height) {
            newHeight = maxSize.height;
        } else {
            if (!dontDeleteHeight) {
                newHeight = '';
            }
        }

        return {
            width: newWidth,
            height: newHeight
        };
    },

    //update the lightbox content which was loaded using ajax
    updateContent: function(responseText)
    {
        var isVisible = this.lightbox.lightboxEl.is(':visible');
        this.lightbox.lightboxEl.show(); //to mesaure

        var originalHeight = this.lightbox.innerLightboxEl.height();
        var originalWidth = this.lightbox.innerLightboxEl.width();

        //do the actual update + callOnContentReady
        Kwf.EyeCandy.Lightbox.Styles.CenterBox.superclass.updateContent.apply(this, arguments);

        if (!this.lightbox.options.height) this.lightbox.innerLightboxEl.css('height', '');
        if (!this.lightbox.options.width) this.lightbox.innerLightboxEl.css('width', '');
        if (isVisible) {
            var newSize = this._getContentSize(true);
            this.lightbox.innerLightboxEl.css(newSize);
            if (this.lightbox.innerLightboxEl.css('backgroundColor')) {
                //animate size only if backgroundColor is set - else it doesn't make sense
                this._center(true);
                this.lightbox.innerLightboxEl.width(originalWidth);
                this.lightbox.innerLightboxEl.height(originalHeight);
                this.lightbox.innerLightboxEl.animate(newSize, {
                    complete: (function() {
                        var newSize = this._getContentSize();
                        this.lightbox.innerLightboxEl.css(newSize);
                    }).bind(this)
                });
            } else {
                this._center(false);
            }
        } else {
            var newSize = this._getContentSize();
            this.lightbox.innerLightboxEl.css(newSize);
            this._center(false);
            this.lightbox.lightboxEl.hide();
        }
    },
    onShow: function() {
        this.mask();
    },
    afterShow: function() {
        this._center();
    },
    onClose: function(options) {
        this.lightbox.lightboxEl.fadeOut({
            complete: (function() {
                this.afterClose();
            }).bind(this)
        });
        this.unmask();
    },
    _getCenterXy: function() {
        var winSize = this._getMaxContentSize(false);
        var xy = {
            left: (winSize.width - this.lightbox.innerLightboxEl.width()) / 2 + $(window).scrollLeft(),
            top: (winSize.height - this.lightbox.innerLightboxEl.height()) / 2 + $(window).scrollTop()
        };

        //if lightbox is larget than viewport don't position lightbox above, the user can only scroll down
        var m = this._getOuterMargin();
        if (xy.left < $(window).scrollLeft()+m) xy.left = $(window).scrollLeft()+m;
        if (xy.top < $(window).scrollTop()+m) xy.top = $(window).scrollTop()+m;
        xy.left = Math.floor(xy.left);
        xy.top = Math.floor(xy.top);

        return xy;
    },
    _center: function(anim) {
        if (!this.lightbox.lightboxEl.is(':visible')) return;
        this.lightbox.innerLightboxEl[anim ? 'animate' : 'css'](this._getCenterXy());
    },

    //called if element *inside* lightbox did fire callOnContentReady
    //it might have changed it's height and we need to adapt the lightbox size
    onContentReady: function()
    {
        if (this.lightbox._blockOnContentReady) return;
        if (!this.lightbox.contentEl) return;

        //adjust size if height changed
        var newSize = this._getContentSize();
        var originalHeight = this.lightbox.innerLightboxEl.height();
        var originalWidth = this.lightbox.innerLightboxEl.width();
        this.lightbox.innerLightboxEl.css(newSize); //set to new size so centering works (no animation)
        var centerXy = this._getCenterXy();

        var position = this.lightbox.innerLightboxEl.position();
        position.left = centerXy.left;
        if (centerXy.top < position.top) position.top = centerXy.top; //move up, but not down
        /*
        //animation to new position disabled, buggy
        this.lightbox.innerLightboxEl.setXY(xy, true);
        this.lightbox.innerLightboxEl.width(originalWidth); //set back to previous size for animation
        this.lightbox.innerLightboxEl.height(originalHeight);
        this.lightbox.innerLightboxEl.setSize(newSize, null, true); //now animate to new size
        */

        //instead center unanimated
        this.lightbox.innerLightboxEl.css(position);
    },

    //the browser window resized, the lightbox content might be responsive - update lightbox size
    onResizeWindow: function(ev)
    {
        if ($(window).width() == this._previousWindowWidth && $(window).height() == this._previousWindowHeight) {
            return;
        }
        this._previousWindowWidth = $(window).width();
        this._previousWindowHeight = $(window).height();

        //reset to initial size so lightbox can grow
        var initialSize = {
            width: null,
            height: null
        };
        if (this.lightbox.options.width) initialSize.width = this.lightbox.options.width;
        if (this.lightbox.options.height) initialSize.height = this.lightbox.options.height;
        this.lightbox.innerLightboxEl.css(initialSize);

        this._resizeContent();
    }
});


text:
import { Nullable } from "babylonjs/types";
import { Color3 } from 'babylonjs/Maths/math.color';
import { Texture } from "babylonjs/Materials/Textures/texture";
import { StandardMaterial } from "babylonjs/Materials/standardMaterial";

import { Scene } from "babylonjs/scene";
/**
 * Class reading and parsing the MTL file bundled with the obj file.
 */
export class MTLFileLoader {
   /**
    * Invert Y-Axis of referenced textures on load
    */
   public static INVERT_TEXTURE_Y = true;

    /**
     * All material loaded from the mtl will be set here
     */
    public materials: StandardMaterial[] = [];

    /**
     * This function will read the mtl file and create each material described inside
     * This function could be improve by adding :
     * -some component missing (Ni, Tf...)
     * -including the specific options available
     *
     * @param scene defines the scene the material will be created in
     * @param data defines the mtl data to parse
     * @param rootUrl defines the rooturl to use in order to load relative dependencies
     * @param forAssetContainer defines if the material should be registered in the scene
     */
    public parseMTL(scene: Scene, data: string | ArrayBuffer, rootUrl: string, forAssetContainer: boolean): void {
        if (data instanceof ArrayBuffer) {
            return;
        }

        //Split the lines from the file
        var lines = data.split('\n');
        //Space char
        var delimiter_pattern = /\s+/;
        //Array with RGB colors
        var color: number[];
        //New material
        var material: Nullable<StandardMaterial> = null;

        //Look at each line
        for (var i = 0; i < lines.length; i++) {
            var line = lines[i].trim();

            // Blank line or comment
            if (line.length === 0 || line.charAt(0) === '#') {
                continue;
            }

            //Get the first parameter (keyword)
            var pos = line.indexOf(' ');
            var key = (pos >= 0) ? line.substring(0, pos) : line;
            key = key.toLowerCase();

            //Get the data following the key
            var value: string = (pos >= 0) ? line.substring(pos + 1).trim() : "";

            //This mtl keyword will create the new material
            if (key === "newmtl") {
                //Check if it is the first material.
                // Materials specifications are described after this keyword.
                if (material) {
                    //Add the previous material in the material array.
                    this.materials.push(material);
                }
                //Create a new material.
                // value is the name of the material read in the mtl file

                scene._blockEntityCollection = forAssetContainer;
                material = new StandardMaterial(value, scene);
                scene._blockEntityCollection = false;
            } else if (key === "kd" && material) {
                // Diffuse color (color under white light) using RGB values

                //value  = "r g b"
                color = <number[]>value.split(delimiter_pattern, 3).map(parseFloat);
                //color = [r,g,b]
                //Set tghe color into the material
                material.diffuseColor = Color3.FromArray(color);
            } else if (key === "ka" && material) {
                // Ambient color (color under shadow) using RGB values

                //value = "r g b"
                color = <number[]>value.split(delimiter_pattern, 3).map(parseFloat);
                //color = [r,g,b]
                //Set tghe color into the material
                material.ambientColor = Color3.FromArray(color);
            } else if (key === "ks" && material) {
                // Specular color (color when light is reflected from shiny surface) using RGB values

                //value = "r g b"
                color = <number[]>value.split(delimiter_pattern, 3).map(parseFloat);
                //color = [r,g,b]
                //Set the color into the material
                material.specularColor = Color3.FromArray(color);
            } else if (key === "ke" && material) {
                // Emissive color using RGB values
                color = value.split(delimiter_pattern, 3).map(parseFloat);
                material.emissiveColor = Color3.FromArray(color);
            } else if (key === "ns" && material) {

                //value = "Integer"
                material.specularPower = parseFloat(value);
            } else if (key === "d" && material) {
                //d is dissolve for current material. It mean alpha for BABYLON
                material.alpha = parseFloat(value);

                //Texture
                //This part can be improved by adding the possible options of texture
            } else if (key === "map_ka" && material) {
                // ambient texture map with a loaded image
                //We must first get the folder of the image
                material.ambientTexture = MTLFileLoader._getTexture(rootUrl, value, scene);
            } else if (key === "map_kd" && material) {
                // Diffuse texture map with a loaded image
                material.diffuseTexture = MTLFileLoader._getTexture(rootUrl, value, scene);
            } else if (key === "map_ks" && material) {
                // Specular texture map with a loaded image
                //We must first get the folder of the image
                material.specularTexture = MTLFileLoader._getTexture(rootUrl, value, scene);
            } else if (key === "map_ns") {
                //Specular
                //Specular highlight component
                //We must first get the folder of the image
                //
                //Not supported by BABYLON
                //
                //    continue;
            } else if (key === "map_bump" && material) {
                //The bump texture
                material.bumpTexture = MTLFileLoader._getTexture(rootUrl, value, scene);
            } else if (key === "map_d" && material) {
                // The dissolve of the material
                material.opacityTexture = MTLFileLoader._getTexture(rootUrl, value, scene);

                //Options for illumination
            } else if (key === "illum") {
                //Illumination
                if (value === "0") {
                    //That mean Kd == Kd
                } else if (value === "1") {
                    //Color on and Ambient on
                } else if (value === "2") {
                    //Highlight on
                } else if (value === "3") {
                    //Reflection on and Ray trace on
                } else if (value === "4") {
                    //Transparency: Glass on, Reflection: Ray trace on
                } else if (value === "5") {
                    //Reflection: Fresnel on and Ray trace on
                } else if (value === "6") {
                    //Transparency: Refraction on, Reflection: Fresnel off and Ray trace on
                } else if (value === "7") {
                    //Transparency: Refraction on, Reflection: Fresnel on and Ray trace on
                } else if (value === "8") {
                    //Reflection on and Ray trace off
                } else if (value === "9") {
                    //Transparency: Glass on, Reflection: Ray trace off
                } else if (value === "10") {
                    //Casts shadows onto invisible surfaces
                }
            } else {
                // console.log("Unhandled expression at line : " + i +'\n' + "with value : " + line);
            }
        }
        //At the end of the file, add the last material
        if (material) {
            this.materials.push(material);
        }
    }

    /**
     * Gets the texture for the material.
     *
     * If the material is imported from input file,
     * We sanitize the url to ensure it takes the textre from aside the material.
     *
     * @param rootUrl The root url to load from
     * @param value The value stored in the mtl
     * @return The Texture
     */
    private static _getTexture(rootUrl: string, value: string, scene: Scene): Nullable<Texture> {
        if (!value) {
            return null;
        }

        var url = rootUrl;
        // Load from input file.
        if (rootUrl === "file:") {
            var lastDelimiter = value.lastIndexOf("\\");
            if (lastDelimiter === -1) {
                lastDelimiter = value.lastIndexOf("/");
            }

            if (lastDelimiter > -1) {
                url += value.substr(lastDelimiter + 1);
            }
            else {
                url += value;
            }
        }
        // Not from input file.
        else {
            url += value;
        }

        return new Texture(url, scene, false, MTLFileLoader.INVERT_TEXTURE_Y);
    }
}


text:
#ifndef LUDI_GRAPHICS_INPUT_ASSEMBLER_STAGE_NULL_H_
#define LUDI_GRAPHICS_INPUT_ASSEMBLER_STAGE_NULL_H_

#if LUDI_GRAPHICS_PLATFORM_ID == LUDI_GRAPHICS_PLATFORM_NULL

namespace ludi {
namespace graphics {
    /*! Represents a null input assembler stage. */
    template <>
    class InputAssemblerStage_<LUDI_GRAPHICS_PLATFORM_NULL> : public InputAssemblerStage_<> {
    private:
        // nothing

    public:
        /*! Constructs an input assembler stage. */
        inline InputAssemblerStage_()
            : InputAssemblerStage_<>()
        {
            // nothing
        }

        /*! Destructor. */
        virtual ~InputAssemblerStage_() {
            // nothing
        }

    public:
        /*! \copydoc InputAssemblerStage_<LUDI_GRAPHICS_PLATFORM_BASE>::Apply() */
        virtual void Apply(reference_ptr<Context*> context, bool force = false) override {}
        /*! \copydoc InputAssemblerStage_<LUDI_GRAPHICS_PLATFORM_BASE>::Restore */
        virtual void Restore() override {}

    public:
        /*! \copydoc InputAssemblerStage_<LUDI_GRAPHICS_PLATFORM_BASE>::BindVertexBuffer */
        virtual void BindVertexBuffer(reference_ptr<Buffer> buffer) override {}
        /*! \copydoc InputAssemblerStage_<LUDI_GRAPHICS_PLATFORM_BASE>::BindIndexBuffer */
        virtual void BindIndexBuffer(reference_ptr<Buffer> buffer) override {}
        /*! \copydoc InputAssemblerStage_<LUDI_GRAPHICS_PLATFORM_BASE>::BindIndexFormat */
        virtual void BindIndexFormat(DataFormat format) override {}
        /*! \copydoc InputAssemblerStage_<LUDI_GRAPHICS_PLATFORM_BASE>::BindTopology */
        virtual void BindTopology(Topology topology) override {}
    };

} // graphics
} // ludi

#endif // LUDI_GRAPHICS_PLATFORM_ID == LUDI_GRAPHICS_PLATFORM_NULL
#endif // LUDI_GRAPHICS_INPUT_ASSEMBLER_STAGE_NULL_H_


text:
/*globals module:true */
module.exports = function(grunt) {
    'use strict';

    grunt.config('releaseNotes', {
        main : {
            src : 'templates/README.template.md',
            dest : 'README.md',
            baseLinkPath : '/tree/master/'
        }
    });
};


text:
Database
########

Persist user-generated content and settings with Elgg's generic storage API.

.. contents:: Contents
   :local:
   :depth: 2

Entities
========

Creating an object
------------------

To create an object in your code, you need to instantiate an
``ElggObject``. Setting data is simply a matter of adding instance
variables or properties. The built-in properties are:

-  **``guid``** The entity's GUID; set automatically
-  **``owner_guid``** The owning user's GUID
-  **``site_guid``** The owning site's GUID. This is set automatically
   when an instance of ``ElggObject`` gets created)
-  **``subtype``** A single-word arbitrary string that defines what kind
   of object it is, for example ``blog``
-  **``access_id``** An integer representing the access level of the
   object
-  **``title``** The title of the object
-  **``description``** The description of the object

The object subtype is a special property. This is an arbitrary string
that describes what the object is. For example, if you were writing a
blog plugin, your subtype string might be *blog*. It's a good idea to
make this unique, so that other plugins don't accidentally try and use
the same subtype. For the purposes of this document, let's assume we're
building a simple forum. Therefore, the subtype will be *forum*:

.. code:: php

    $object = new ElggObject();
    $object->subtype = "forum";
    $object->access_id = 2;
    $object->save();

``access_id`` is another important property. If you don't set this, your
object will be private, and only the creator user will be able to see
it. Elgg defines constants for the special values of ``access_id``:

-  **ACCESS_PRIVATE** Only the owner can see it
-  **ACCESS_FRIENDS** Only the owner and his/her friends can see it
-  **ACCESS_LOGGED_IN** Any logged in user can see it
-  **ACCESS_PUBLIC** Even visitors not logged in can see it

Saving the object will automatically populate the ``$object->guid``
property if successful. If you change any more base properties, you can
call ``$object->save()`` again, and it will update the database for you.

You can set metadata on an object just like a standard property. Let's
say we want to set the SKU of a product:

.. code:: php

    $object->SKU = 62784;

If you assign an array, all the values will be set for that metadata.
This is how, for example, you set tags.

Metadata cannot be persisted to the database until the entity has been
saved, but for convenience, ElggEntity can cache it internally and save
it when saving the entity.

Loading an object
-----------------

By GUID
~~~~~~~

.. code:: php

    $entity = get_entity($guid);
    if (!$entity) {
        // The entity does not exist or you're not allowed to access it.
    }

But what if you don't know the GUID? There are several options.

By user, subtype or site
~~~~~~~~~~~~~~~~~~~~~~~~

If you know the user ID you want to get objects for, or the subtype, or
the site, you have several options. The easiest is probably to call the
procedural function ``elgg_get_entities``:

.. code:: php

    $entities = elgg_get_entities(array(
        'type' => $entity_type,
        'subtype' => $subtype,
        'owner_guid' => $owner_guid,
    ));

This will return an array of ``ElggEntity`` objects that you can iterate
through. ``elgg_get_entities`` paginates by default, with a limit of 10;
and offset 0.

You can leave out ``owner_guid`` to get all objects and leave out subtype
or type to get objects of all types/subtypes.

If you already have an ``ElggUser`` – e.g. ``elgg_get_logged_in_user_entity``,
which always has the current user's object when you're logged in – you can
simply use:

.. code:: php

    $objects = $user->getObjects($subtype, $limit, $offset)

But what about getting objects with a particular piece of metadata?

By metadata
~~~~~~~~~~~

The function ``elgg_get_entities_from_metadata`` allows fetching entities
with metadata in a variety of ways.

By annotation
~~~~~~~~~~~~~

The function ``elgg_get_entities_from_annotations`` allows fetching entities
with metadata in a variety of ways.

.. note::

   As of Elgg 1.10 the default behaviour of `elgg_get_entities_from_annotations` was brought inline with the rest of the `elgg_get_entities*` functions.

   Pre Elgg 1.10 the sorting of the entities was based on the latest addition of an annotation (in $options your could add `$options['order_by'] = 'maxtime ASC'` or `$options['order_by'] = 'maxtime DESC'`. As of Elgg 1.10 this was changed to the creation time of the entity, just like the rest of the `elgg_get_entities*` functions.
   To get the old behaviour back add the following to your `$options`:

   .. code:: php

      $options['selects'] = array('MAX(n_table.time_created) AS maxtime');
      $options['group_by'] = 'n_table.entity_guid';
      $options['order_by'] = 'maxtime ASC'

      or

      $options['order_by'] = 'maxtime DESC'

Displaying entities
-------------------

In order for entities to be displayed in listing functions you need
to provide a view for the entity in the views system.

To display an entity, create a view EntityType/subtype where EntityType
is one of the following:

object: for entities derived from ElggObject
user: for entities derived from ElggUser
site: for entities derived from ElggSite
group: for entities derived from ElggGroup

A default view for all entities has already been created, this is called
EntityType/default.

.. _guides/database#entity-icons:

Entity Icons
~~~~~~~~~~~~

Every entity can be assigned an icon which is retrieved using the ``ElggEntity::getIconURL($params)`` method.
This method accepts a ``$params`` argument that can be either a string specifying on of the configured icon sizes,
or an array of parameters, that specify the size and provide additional context for the hook to determine the icon
to serve.

Use ``elgg_get_config('icon_sizes')`` to get all possible values. The following sizes exist by default:
``'large'``, ``'medium'``, ``'small'``, ``'tiny'``, and ``'topbar'``. The method triggers the
``entity:icon:url`` :ref:`hook <guides/hooks-list#other>`.

Use ``elgg_view_entity_icon($entity, $size, $vars)`` to render an icon. This will scan the following
locations for a view and include the first match.

#. views/$viewtype/icon/$type/$subtype.php
#. views/$viewtype/icon/$type/default.php
#. views/$viewtype/icon/default.php

Where

$viewtype
	Type of view, e.g. ``'default'`` or ``'json'``.
$type
	Type of entity, e.g. ``'group'`` or ``'user'``.
$subtype
	Entity subtype, e.g. ``'blog'`` or ``'page'``.

By convention entities that have an uploaded avatar or icon will have the ``icontime`` property
assigned. This means that you can use ``$entity->icontime`` to check if an icon exists for the given
entity.

Adding, reading and deleting annotations
----------------------------------------

Annotations could be used, for example, to track ratings. To annotate an
entity you can use the object's ``annotate()`` method. For example, to
give a blog post a rating of 5, you could use:

.. code:: php

    $blog_post->annotate('rating', 5);

.. _view: Views

To retrieve the ratings on the blog post, use
``$blogpost->getAnnotations('rating')`` and if you want to delete an
annotation, you can operate on the ``ElggAnnotation`` class, eg
``$annotation->delete()``.

Retrieving a single annotation can be done with ``get_annotation()`` if
you have the annotation's ID. If you delete an ElggEntity of any kind,
all its metadata, annotations, and relationships will be automatically
deleted as well.

Extending ElggEntity
--------------------

If you derive from one of the Elgg core classes, you'll need to tell
Elgg how to properly instantiate the new type of object so that
get\_entity() et al. will return the appropriate PHP class. For example,
if I customize ElggGroup in a class called "Committee", I need to make
Elgg aware of the new mapping. Following is an example class extension:

.. code:: php

    // Class source
    class Committee extends ElggGroup {

        protected function initializeAttributes() {
            parent::initializeAttributes();
            $this->attributes['subtype'] = 'committee';
        }

        // more customizations here
    }

    function committee_init() {

        register_entity_type('group', 'committee');

        // Tell Elgg that group subtype "committee" should be loaded using the Committee class
        // If you ever change the name of the class, use update_subtype() to change it
        add_subtype('group', 'committee', 'Committee');
    }

    register_elgg_event_handler('init', 'system', 'committee_init');

Now if you invoke ``get_entity()`` with the GUID of a committee object,
you'll get back an object of type Committee.

This template was extracted from the definition of ElggFile.

Advanced features
-----------------

Entity URLs
~~~~~~~~~~~

Entity urls are provided by the ``getURL()`` interface and provide the
Elgg framework with a common way of directing users to the appropriate
display handler for any given object.

For example, a profile page in the case of users.

The url is set using the ``elgg\_register\_entity\_url\_handler()``
function. The function you register must return the appropriate url for
the given type - this itself can be an address set up by a page handler.

.. _getURL(): http://reference.elgg.org/classElggEntity.html#778536251179055d877d3ddb15deeffd
.. _elgg\_register\_entity\_url\_handler(): http://reference.elgg.org/entities_8php.html#f28d3b403f90c91a715b81334eb59893

The default handler is to use the default export interface.

Entity loading performance
~~~~~~~~~~~~~~~~~~~~~~~~~~

``elgg_get_entities`` has a couple options that can sometimes be useful to improve performance.

- **preload_owners**: If the entities fetched will be displayed in a list with the owner information, you can set this option to ``true`` to efficiently load the owner users of the fetched entities.
- **preload_containers**: If the entities fetched will be displayed in a list using info from their containers, you can set this option to ``true`` to efficiently load them.
- **distinct**: When Elgg fetches entities using an SQL query, Elgg must be sure that each entity row appears only once in the result set. By default it includes a ``DISTINCT`` modifier on the GUID column to enforce this, but some queries naturally return unique entities. Setting the ``distinct`` option to false will remove this modifier, and rely on the query to enforce its own uniqueness.

The internals of Elgg entity queries is a complex subject and it's recommended to seek help on the Elgg Community site before using the ``distinct`` option.

Pre-1.8 Notes
-------------

update\_subtype(): This function is new in 1.8. In prior versions, you
would need to edit the database by hand if you updated the class name
associated with a given subtype.

elgg\_register\_entity\_url\_handler(): This function is new in 1.8. It
deprecates register\_entity\_url\_handler(), which you should use if
developing for a pre-1.8 version of Elgg.

elgg\_get\_entities\_from\_metadata(): This function is new in 1.8. It
deprecates get\_entities\_from\_metadata(), which you should use if
developing for a pre-1.8 version of Elgg.

Custom database functionality
=============================

It is strongly recommended to use entities wherever possible. However, Elgg
supports custom SQL queries using the database API.

Example: Run SQL script on plugin activation
--------------------------------------------

This example shows how you can populate your database on plugin activation.

my_plugin/activate.php:

.. code:: php

    if (!elgg_get_plugin_setting('database_version', 'my_plugin') {
        run_sql_script(__DIR__ . '/sql/activate.sql');
        elgg_set_plugin_setting('database_version', 1, 'my_plugin');
    }

my_plugin/sql/activate.sql:

.. code:: sql

    -- Create some table
    CREATE TABLE prefix_custom_table(
        id INTEGER AUTO_INCREMENT,
        name VARCHAR(32),
        description VARCHAR(32),
        PRIMARY KEY (id)
    );

    -- Insert initial values for table
    INSERT INTO prefix_custom_table (name, description)
    VALUES ('Peter', 'Some guy'), ('Lisa', 'Some girl');

Note that Elgg execute statements through PHPs built-in functions and have
limited support for comments. I.e. only single line comments are supported
and must be prefixed by "-- " or "# ". A comment must start at the very beginning
of a line.

Systemlog
=========

.. note::

   This section need some attention and will contain outdated information

The default Elgg system log is a simple way of recording what happens within an Elgg system. It's viewable and searchable directly from the administration panel.

System log storage
------------------

A system log row is stored whenever an event concerning an object whose class implements the :doc:`/design/loggable` interface is triggered. ``ElggEntity`` and ``ElggExtender`` implement :doc:`/design/loggable`, so a system log row is created whenever an event is performed on all objects, users, groups, sites, metadata and annotations.

Common events include:

- create
- update
- delete
- login

Creating your own system log
----------------------------

There are some reasons why you might want to create your own system log. For example, you might need to store a full copy of entities when they are updated or deleted, for auditing purposes. You might also need to notify an administrator when certain types of events occur.

To do this, you can create a function that listens to all events for all types of object:

.. code:: php

   register_elgg_event_handler('all','all','your_function_name');

Your function can then be defined as:

.. code:: php

   function your_function_name($object, $event) {
      if ($object instanceof Loggable) {
         ...
      }
   }

You can then use the extra methods defined by :doc:`/design/loggable` to extract the information you need.


text:
#ifndef LLIST_H
#define LLIST_H

struct LINKED_LIST_ELEMENT {
    void* key;
    void* data;
    struct LINKED_LIST_ELEMENT* next;
};

struct LINKED_LIST {
    struct LINKED_LIST_ELEMENT* first;
    int (* comparator)(void* lhs, void* rhs);
};

void  llist_init(struct LINKED_LIST** llist, int (* func)(void* lhs, void* rhs));
int   llist_ready(struct LINKED_LIST* llist);
void* llist_update(struct LINKED_LIST* llist, void* key);
void* llist_get(struct LINKED_LIST* llist, void* key);
void* llist_delete(struct LINKED_LIST* llist, void* key);
int   llist_empty(struct LINKED_LIST* llist);

#endif /* LLIST */


text:
#include <stdlib.h>
#include "op_libiberty.h"
#include "op_popt.h"

poptContext op_poptGetContext(char const * name,
		int argc, char const ** argv,
		struct poptOption const * options, int flags)
{
	poptContext optcon;
	int c;

	xmalloc_set_program_name(argv[0]);

#ifdef CONST_POPT
	optcon = poptGetContext(name, argc, argv, options, flags);
#else
	optcon = poptGetContext((char *)name, argc, (char **)argv, options, flags);
#endif

	c = poptGetNextOpt(optcon);

	if (c < -1) {
		fprintf(stderr, "%s: %s: %s\n", argv[0],
			poptBadOption(optcon, POPT_BADOPTION_NOALIAS),
			poptStrerror(c));
		poptPrintHelp(optcon, stderr, 0);
		exit(EXIT_FAILURE);
	}

	return optcon;
}


text:
#include "vsx_common.h"

//
// Fulfill linker definitions for functionality that should not be present in mgr build
//

//stream/stream_abr.c
int stream_abr_cbOnStream(struct STREAM_STATS *pStreamStats) {
  return 0;
}

void stream_abr_close(STREAM_ABR_T *pAbr) {
}

/*
//stream/stream_monitor.c
int stream_monitor_start(STREAM_STATS_MONITOR_T *pMonitor,
                         const char *statfilepath,
                         unsigned int intervalMs) {
  return 0;
}
int stream_monitor_stop(STREAM_STATS_MONITOR_T *pMonitor) {
  return 0;
}
STREAM_STATS_T *stream_monitor_createattach(STREAM_STATS_MONITOR_T *pMonitor,
                                            const struct sockaddr *psaRemote,
                                            STREAM_METHOD_T method,
                                            STREAM_MONITOR_ABR_TYPE_T abrEnabled) {
  return 0;
}
int stream_stats_destroy(STREAM_STATS_T **ppStats, pthread_mutex_t *pmtx) {
  return 0;
}
*/

//stream/stream_srtp.c
int srtp_loadKeys(const char *in,  SRTP_CTXT_T *pCtxtV, SRTP_CTXT_T *pCtxtA) {
  return 0;
}

const char *srtp_streamTypeStr(SRTP_AUTH_TYPE_T authType, SRTP_CONF_TYPE_T confType, int safe) {
  static const char *s_srtpStreamTypes[] = { "" };

  return s_srtpStreamTypes[0];
}

int srtp_streamType(const char *streamTypeStr, SRTP_AUTH_TYPE_T *pAuthType, SRTP_CONF_TYPE_T *pConfType) {
  return 0;
}

int srtp_createKey(SRTP_CTXT_T *pCtxt) {
  return 0;
}

int srtp_sendto(const NETIO_SOCK_T *pnetsock,
                void *buffer,
                size_t length,
                int flags,
                const struct sockaddr *pdest_addr,
                const SRTP_CTXT_T *pSrtp,
                enum SENDTO_PKT_TYPE pktType,
                int no_protect) {
  return 0;
}

// stream/stream_dtls.c
int dtls_str2fingerprint(const char *str, DTLS_FINGERPRINT_T *pFingerprint) {
  return 0;
}

char *dtls_fingerprint2str(const DTLS_FINGERPRINT_T *pFingerprint, char *buf, unsigned int len) {
  return buf;
}

int dtls_get_cert_fingerprint(const char *certPath, DTLS_FINGERPRINT_T *pFingerprint) {
  return 0;
}