Categories
Uncategorised

Vue

Templates

Vue templates end in .vue and can have three sections; template, script and style.

A lang attribute can be applied to the style tag to use other preprocessor languages;

<style lang="scss">

Styles included in a template are split out and combined into a separate CSS file. Using SCSS allows us to use import and SCSS language features within a template file;

@import "../../scss/components/light-component";
<style lang="scss">

Child Components

TODO!

Data

Initialise a Vue component with a data object. Return this from the data function when on initialisation, or include it in the script part of the .vue template file.

Data can be modified ‘live’, and will be re-rendered when the data changes. It’s a bit like KnockoutJS, but doesn’t have observer object nonsense and function calls to return the primitive value of data. Instead it uses Javascript’s getters and setters which are actually method calls on the object. Each data key defined will have a corresponding get and set method defined on the component.

Viewing a vue component in the console shows the getters and setters at the end of the object definition which all link to the same proxyGetter`` andproxyGetter“` methods. In Vue 3, a native Javascript proxy object is used instead of Vue’s own implementation.

Data values can be edited live in the browser. Installing Vue Browser Dev tools will provide an easier way to modify and debug functionality without assigning the app or component to a global window variable.

Data keys are accessible on the component as first party variables.

Props

Props are a way for a component to receive data in a read-only fashion. They don’t show in the Vue Dev tools and aren’t changeable. Think of props in a component like “arguments in a function” in PHP.

Props are accessible in templates in the same way as data keys, using curly bracket notation.

Props can be defined as an array or an object in our module using the following syntax. This allows us to specify types for props.

Array – no validation.

props: ['title'],

Objects #1 – define type

props: {
  title: String
}

Object 2 – with required

props: {
  title: {
    type: String,
    required: true
  }
}

Default Values

Use the default key when defining the prop;

props: {
  title: {
    type: String,
    required: true,
    default: "I'm the default value"
  }
}

It’s advisable to use the more verbose syntax and define types for props. We can also set a ‘required’ key here.

To pass a prop to a component, define it as an attribute on the component’s tag;

<legend-component title="Ooh matron!" />

Data Location ### 

Data should live in one place, on the deepest component which requires it, and then passed to child components via props.

When data is passed to a child component via a prop, the prop Should not be changed by the child. The value will update, but the parent will not be notified.

Communication UP with $emit (Events)

Broadcast events for parent components to listen to using

  methods: {
    toggleCollapsed() {
      this.$emit('toggle-collapsed');
    },
  },

Simple events can also be included inline in templates, rather than calling a method;

<button @click="$emit('toggle-collapsed')">Click</button>

this is automatically assumed when referencing properties in a template

We can then listen to this event when defining the component in a parent template using

<sidebar :collapsed="sidebarCollapsed" 
   @toggle-collapsed="toggleSidebarCollapsed" 
/>

@ is a shortcut for v-on:

  methods: {
    toggleSidebarCollapsed() {
      this.sidebarCollapsed = !this.sidebarCollapsed;
    },
  },

This passes :collapsed as a prop into the sidebar component. When the sidebar $emits the toggle-collapsed event, the toggleSidebarCollapsed method is called, this.sidebarCollapsed is updated, and propogated back to the sidebar component via the prop link.

Events being broadcast can be observed in the Vue Dev Tools’ Events tab in realtime.

v-bind: Dynamic Attributes

To define a dynamic value when passing in a prop, use v-bind. This uses the key from the data array as the value of the attribute, which must be prepended with v-bind:. v-bind has the shortcut of colon.

<legend-component v-bind:title="legend" />

This will take the “legend” value of the parent component’s data key and re-render the child component when it changes. The value in the attribute is actually a javascript expression, so things can be done such as;

<legend-component v-bind:title="legend + ' extra text'" />

which will concatenate the string onto the value when it changes.

v-bind: Shorthand

Use

<legend-component :title="legend + ' extra text'" />

which is an alias for v-bind.

Modular Styles

When including styles in a vue template, we can use the ‘module’ attribute to tell vue to suffix our CSS with a random string.

<style lang="scss" module>

This allows us to access modular styles in our template using the special $style variable which is made available. Use :class as a shortcut to the v-bind method.

The style object is a property of the Vue component. access

<div :class="$style.sidebar">

Class can also use an array of elements if other classes need to be used alongside the module generated class name. Use the following;

<div :class="[$style.sidebar, 'p-3', 'mb-5']">

Another trick of :class is the use of an object instead of an array. This allows us to use the classnames as keys, and set whether they should be active or not. To use dynamic keys, such as the $style.sidebar above, it needs to be wrapped in square brackets. Confusing as it looks like an array.

  <div :class="{ 
    [$style.component]: true, 
    'p-3': true, 
    'mb-5': true 
    }">

:global – don’t namespace a child class

When Vue generates module CSS classes for the template, it will also do so for child classes within our component. E.g.

<style lang="scss" module>
.component {

  ul {
    li.selected {
      background: $light-component-border;
     }
  }
}
</style>

Would produce classes such as 

```css
.sidebar_component_1vx3Z ul li.selected_2dxwF

Where the second hash is not required; the encapsulating hash is sufficient to namespace the class to the component. To exclude classes, add <code>:global</code> before the style declaration;

    :global li.selected { 

Which will now produce

.sidebar_component_1vx3Z ul li.selected

<h3>Using :global on the root component</h3>

Typically, using a namespaced root component is enough for our component; we don't need other classes to be hashed. To do this, so that we don't have to declare all child classes as <code>:global</code>, we can do the following;

.component :global {

### Module Classes & Dev Mode ###
Dynamically generated classnames can be awkward to debug in dev mode. Use this in <code>webpack.config.js</code> to

    .configureCssLoader((config) => {
        if (!Encore.isProduction() && config.modules) {
            config.modules.localIdentName = '[name]_[local]_[hash:base64:5]';
        }
    })
```

The [name] key is the filename of the component, E.g. products.vue would be 'products'. The [local] key is the classname, so 'sidebar' in this instance. Then we add a base64 hash with a length of ':5'.

This allows us to see what file a style exists in in dev mode.

Aliases

Aliases allow us to set base directories to use when importing files, this then negates the use of relative directory links. Adding the following to our webpack.config.js

.addAliases({
        '@': path.resolve(__dirname, 'assets', 'js'),
        styles: path.resolve(__dirname, 'assets', 'scss'),
    })

will allow us to use @ when importing javascript

import LegendComponent from '@/components/legend';

And ‘styles’ when importing styles into a javascript file;

import 'styles/app.scss';

However tilde must be prepended to the styles key when importing into a style tag;

@import "~styles/components/light-component";

Looping in Templates

Use the v-for attribute on the attribute which is to be looped over. This can be used for arrays and objects.

<li v-for="category in categories" class="nav-item">
    <a class="nav-link" :href="category.link">{{ category.name }}</a>
</li>

When using dynamic attributes like the href, remember to prepend with a colon to execute it as a javascript statement. The above template would render the following data;

    data() {
        return {
            categories: [{
                name: 'Horse Pringers',
                link: '#'
            }, {
                name: 'Amiga Hampers',
                link: '#'
            }]
        };
    },

This should however always be accompanied by a key attribute so that Vue can retain the element’s context and re-render it when required. VSCode will show an error when using the Vue extensions.

The v-for vue directive attribute should also be changed to include the key as the second parameter in the loop. The key attribute should also be prepended with a colon.

<li v-for="(category, index) in categories" :key="index" class="nav-item">

The key attribute does not render in the source code of the page as it’s a special attribute, which can be found here

Rendering an Element’s Contents – v-text

This can either be achieved using the curly brace syntax or using the v-text attribute, which is another vue directive. This can also contain standard javascript such as ternary conditionals;

<button class="btn btn-secondary btn-sm" 
   v-text="collapsed ? '>>' : '<< Collapse'">
</button>

Escaping

Vue automatically escapes HTML characters in strings when rendering in templates.

Events – v-on

Adding events to elements using the v-on directive. The shortcut for this is the @ symbol. Vue automatically prepends methods v-on on events with this., so the following actually becomes this.toggleCollapsed

<button class="btn btn-secondary btn-sm" 
   v-on:click="toggleCollapsed">
</button>

@ shortcut

<button class="btn btn-secondary btn-sm" 
      @click="toggleCollapsed">
</button>

append the regular javascript event after the colon. Target a method defined in the “`methods“ object in the component definition;

export default {
    name: 'Sidebar',
    data() {
        return {
            collapsed: false,
        };
    },
    methods : {
        toggleCollapsed() {
            this.collapsed = !this.collapsed;
        }
    }
}

Component Structure

Component properties which start with dollar are created internally by Vue, and can be manipulated if required for more advanced operations. Methods starting with underscore should be treated as private and not used.

These can however be useful when debugging and can be output in the component. E.g. every instantiated component is assigned a _uid which can be output in the template using

{{ _uid }}

It would appear that this was adopted to avoid conflicts with user created methods.

## Component instantiation – created() ##
When a component instantiates, its created method is automatically called if defined.

Conditionals – v-if and v-show Directives

A v-if on an element will completely remove it from the dom when the conditional doesn’t pass.

<div v-if="!collapsed">

A v-show conditional hides the element with display:none

<div v-show="!collapsed">

Showing should be used for simple elements which hide and appear frequently, and v-if should be used for more complex elements which reduces Vue’s rendering time when removed completely.

‘component’ root Style convention

It’s considered convention to call the root of a component’s style ‘component’. When configureCssLoader is used in development, the class name will be prepended with the name of the template file it exists in. Class names are only more cryptic in production.

Computed Properties

Computed properties allow us to take logic out of our template and into our component javascript. They don’t accept parameters, and behave just like a property on the component.

Instead of doing inline logic to switch classes for example;

  <div
    :class="{
      [$style.component]: true,
      [$style.collapsed]: collapsed,
      'p-3': true,
      'mb-5': true,
    }"
  >

We can instead do the following. Computed methods are called as though they are properties in templates javascript files.

<div :class="componentClass">

And then define our computed method in the component’s computed key;

  computed: {
    componentClass() {
      const classes = [this.$style.component, "p-3", "mb-5"];

      if(this.collapsed) {
        classes.push(this.$style.collapsed);
      }
 
      return classes;
    },

Note that classes are accessed through the $style object. This ensures we use the generated classes with transformations.

Computed & Ordering

For convention, the ‘computed’ key should be before the ‘methods’ key in a component definition.

### Performance ###
Computed methods will only run if a property referenced in the method changes on the object. So, in the above example, if we had a button which called

methods: {
    toggleCollapsed() {
      this.collapsed = !this.collapsed;
    },
},

then componentClass would update the class on the element. If we were to remove the line which modifies the collapsed property, the componentClass function would not execute!

Shared CSS

Normal shared styles should be imported and used with components where appropriate, and used as regular strings rather than using the $style object.

This will work for global styles, but for shared styles which are imported into a component, by default they may be duplicated with the module’s prefix.

To get around this, we can add a second style tag, with a lang of “css”. SCSS can be imported into this style tag, but using “scss” as the lang attribute “for some reason” duplicates the styles.

<style lang="css>
@import '~path/to/style.scss'
</style>

AJAX With Axios

yarn add axios --dev

This is an alternative to the browser's built in 'fetch' method, however this is not supported in IE 11.

Hook Methods

We can use the methods mounted and created to perform actions when we use a component. Mounted when it’s actually added to the page.

To call an ajax endpoint when a component mounts;

  mounted() {
    axios.get('/api/products').then((response) => {
        // Do things.
    });
  }

Use of created

The created hook can often be the better hook for performing ajax requests as it will start as soon as the component is created rather than added to the page.

  created() {
    axios.get('/api/products').then((response) => {
        // Do things.
    });
  }

await & async

This waits for an AJAX request to complete before continuing code execution. It’s also legal to use await on function which do not return promises, they’re just executed and returned instantly. To use this, the encapsulated method must have the async keyword before it;

async mounted() {
    const response = await axios.get('/api/products');
  }

When an async method is defined, it will always return a Promise. Only the code in the async method will pause whilst an await call is made, the rest of the application code will continue execution. The returned promise can be used to chain other operations which may require the data returned in the async method.

export default {
  name: "Catalog", 
  data: () => ({
    products: []
  }),
  async mounted() {
    const response = await axios.get('/api/products');
    this.products = response.data['hydra:member'];
  }
};

## API Platform ##
When using <a href="https://api-platform.com/">API Platform</a>, accessing the API in a browser will give the GUI. It does this by checking the ```accept``` header. To access endpoints which AJAX calls directly, add ```.jsonld``` to the end of the url.

### @id and API Platform ###
Instead of the traditional use of primary key database ids when assigning keys to objects (mainly in loops), the ```@id``` attribute can also be used, which contains the unique URI for the item in question. This can be more useful than just using the ```id``` primary key. This is known as the IRI.

## Smart Component, Dumb Component ##
The logical hierarchy of components should be defined by their usage. Creating a product list component could load the products and render them, however defining its data as a prop which is set by a "smart" component can be preferable.

A smart component can be considered like a Controller, and dumb components akin to templates.

### catalog.vue ###

<template>
<div>
<div class="row">
<div class="col-12">
<h1>Products</h1>
</div>
</div>

&lt;product-list :products=&quot;products&quot; /&gt;

</div>
</template>

<script>
import axios from 'axios';
import ProductList from '@/components/product-list';

export default {
name: "Catalog",
components: {
ProductList
},
data: () => ({
products: [],
}),
async mounted() {
const response = await axios.get('/api/products');
this.products = response.data['hydra:member'];
}
};
</script>

<br />### product-list/index.vue ###
<template>
  <div class="row">
    <div
      v-for="product in products"
      :key="product['id']"
      class="col-xs-12 col-6 mb-2 pb-2"
    >
      {{ product.name }}
    </div>
  </div>
</template>

<script>
export default {
    name: 'ProductList',
    props: {
        products: {
            type: Array,
            required: trueprodu
        }
    },
    data: {
        products: []
    }
};
</script>

In this example, the catalog component is responsible for providing the data for the product-list component. The import for the product list does not need to include the ‘index’ part of the file path. This is assumed by Vue when we import a directory.

Passing Server Data to Vue

Access the window object in computed return methods to initialise the Vue app with data on page load. Whilst this is legal, it often gets messy so it’s better to use something like JS Services to centralise the data.

Initializing Vuw with data on the page is a preferred approach to stop the initial load ‘pop’ when ajaxing in data.

Services

It’s often better to split functionality up into smaller pieces, rather than have it all lumped together in the component’s template file. We can create smaller service methods to achieve this, so that things like AJAX requests are separated from our component’s logic.

Vue Lifecycle

Taken from here

Categories
Uncategorised

Webpack – Assets

By default, Webpack only deals with javascript. For other filetypes, we need to add loaders to our config. We define these in the rules section of our config file, providing a regex for the test key for the files to be dealt with (typically file extension).

{
...
 rules: [
            {
                test: /\.css$/
                ...
            }
        ]
...
}

If we want to exclude files for any reason, we can add an exclude key, which is also a regex

 rules: [
            {
                test: /\.css$/,
                exclude: /file-not-to-be-processed.css/
                ...
            }
        ]  

CSS

Let’s add a CSS file to our project in src/css/style.css

body{
    background: red;
}

Now we need to include this file in our src/index.js file.

import './css/style.css';

In our webpack.config.js file, we can now add a definition for different filetypes which match on a filename regex:

const path = require('path');

module.exports = {
    entry: './src/index.js',
    output: {
        filename: 'bundle.js',
        path: path.resolve(__dirname, 'dist')
    },
    module: {
        rules: [
            {
                test: /\.css$/,
                use: [
                    'style-loader',
                    'css-loader'
                ]
            }
        ]
    }
};

And then install the css-loader and style-loader

npm install style-loader css-loader -D

When processing files, the use array is processed from top to bottom.
The CSS Loader loads CSS files, and deals with any assets within the file. Then the result is passed to the Style Loader which injects the CSS onto the page using a style tag.

In the example above, the the loaders are passed in order as strings in an array. If we need to configure the loaders with options, for example to enable source maps, we can use an object instead of a string, and provide an options key:

{
...
 rules: [
            {
                test: /\.css$/,
                use: [
                    {
                        loader: 'style-loader'
                    },
                    {
                        loader: 'css-loader',
                        options: {
                            sourceMap: true
                        }
                    }
                ]
            }
        ]
...
}

We will now be able to see files and line numbers when inspecting elements in the dev tools.

By default, the style-loader will create a separate style tag for each file being imported. To coalesce them into a single style tag, we can provide a singleton option key:

...
{
    loader: 'style-loader',
    options: {
        sourceMap: true,
        singleton: true
    }
}
...

Outputting CSS To A File

Instead of including all of the CSS in style tags, we can instead output them to a file. We’ll use the MiniCssExtractPlugin to achieve this.

npm install -D mini-css-extract-plugin

And then include it at the top of our config file

const MiniCssExtractPlugin = require('mini-css-extract-plugin');

We can then need to use this as a plugin which will output our file

const MiniCssExtractPlugin = require('mini-css-extract-plugin');

{
...
 plugins: [
        new MiniCssExtractPlugin({
            filename: "style.css"
        })
    ],
...
}

This also requires a loader to be added to the process chain. This plugin, will replace the style-loader which we used earlier.

{
...
    rules: [
            {
                test: /\.css$/,
                use: [
                    {
                        loader: MiniCssExtractPlugin.loader
                    },
                    { 
                        loader: "css-loader"
                    }  
                ]
            }
        ]
...
}

We can now link to dist/styles.css from within our HTML file

<link rel="stylesheet" href="dist/style.css">

Dynamically Including CSS

In the example above, we have to hardcode our output CSS file within our HTML file. This would be cumbersome if we were using a hashed filename which would re-generate dynamically. We can achieve dynamic importing using the HTML Webpack Plugin

npm install -D html-webpack-plugin

Now we can remove any hardcoded script or CSS tags from our index.html, and move it to the ./src folder. Next, we can add the plugin definition

{
...
 plugins: [
        ...
        new MiniCssExtractPlugin({
            filename: "style.css",
        }),
        new HTMLWebpackPlugin({
            filename: '../index.html',
            template: './src/index.html'
        })
    ],
...
}

File Hashing

By default, the index.html file will be built in our dist folder, we’ll place this one level above in this example. We are now able to introduce file hashing to our application, as the CSS files are being injected dynamically. This means that if any of our file contents change, such as adding a new CSS rule, the filename will change and the user will always request the newest version.

There are two ways to do this, we can either use the html-webpack-plugin to append a querystring hash to the end of our static filenames, or we can use the mini-css-extract-plugin to create a hashed filename for our CSS. We can also use a combination of the two.

{
...
 plugins: [
        new CleanWebpackPlugin(['dist']),
        new MiniCssExtractPlugin({
            filename: '[contenthash].css'
        }),
        new HTMLWebpackPlugin({
            filename: '../index.html',
            template: './src/index.html',
            hash: true
        })
    ],
...
}

The above example will do both, using [contenthash] as the filename and hash: true in the HTMLWeboackPlugin.

Taking this further, we can now use contenthash when including our javascript file in Webpack’s config, so instead of using just main.js, we can use

{
...
    output: {
        filename: '[name].[contenthash].js'
        ...
    }
...
}

contenthash should be used when we need to know if a particular piece of content changes. Using chunkhash or hash will regenerate when content outside of our context changes. E.g. If we change CSS, then the JS’s file hash will also change.

It should be noted, that using HTMLWebpackPlugin’s hash option uses webpack’s hash for the build, which will change when the entire build changes. Therefore, when we’re using contenthash to generate filenames, we should turn off this option to avoid unnecessary downloads.

{
...
   plugins: [
        new HTMLWebpackPlugin({
            filename: '../index.html',
            hash: false
        })
   ]
...
}

Minifying CSS

All of the CSS we’ve been generating so far has been un-minified. To minify it for production, we can use the OptimiseCssAssetPlugin.

npm install -D optimize-css-assets-webpack-plugin

We can then use it by adding its plugin to our definition

{
   ...
    plugins: [
        new CleanWebpackPlugin(['dist'], { watch: false }),
        new MiniCssExtractPlugin({
            filename: "[contenthash].css",
        }),
        new HTMLWebpackPlugin({
            filename: '../index.html',
            hash: false,
            cache: true
        }),
        new OptimizeCssAssetsPlugin({})
    ],
   ...
}

Adding a HTML Template

By default, our index.html file will be generated automatically for us. Using the HTMLWebpackPlugin, we can specify a template file for the plugin to use which may contain our initial HTML structure. Create a file in src/index.html and then add a template key to our HTMLWebpackPlugin config

{
...
    plugins: {
    ...
        new HTMLWebpackPlugin({
            filename: '../index.html',
            template: './src/index.html',
            hash: false,
            cache: true
        }),
   ...
   }
...
}
<!doctype html>
<html>
 <head>
   <title>Getting Started</title>
 </head>
 <body>
    <header>HEADER</header>
 </body>
</html>

The CSS will now be added to the head of the template, and JS files will be added at the end of the HTML tag.

Sass

Sass compiled much the same way as standard CSS, but it uses two extra Webpack plugins to achieve it, Sass Loader, and Node Sass

npm install node-sass sass-loader -D

And then create a rule in our Webpack config

{
   ...
 rules: [
       ...
            {
                test: /\.scss$/,
                use: [
                    {
                        loader: MiniCssExtractPlugin.loader
                    },
                    {
                        loader: "css-loader"
                    },
                    {
                        loader: "sass-loader"
                    }
                ]
            }
      ...
     ]
}

We can then create a Sass file in our src directory, and import it in the same way as our previous CSS file. This will then be combined into our dist folder’s output CSS.

Images

Images in our CSS can be handled using the url-loader Webpack plugin.

npm install url-loader url-loader -D

And then add a loader rule to our config

test: /\.(png|svg|jpg|gif)$/,
use: {
    loader: 'url-loader',
    options: {
        name: '[path][name].[ext]',
        context: 'src',
        limit: 9000
    }
}

This will copy images used in our CSS or SASS and place them in the dist folder. The path folder by default will include our src directory, so specifying the context: src key, will tell url-loader not to include that path in our output directory. We can also specify a limit (in bytes), which will include any images under that size inline as a data-url in our application; this is used to limit server requests for small images.

This will work for images in CSS, however images imported using javascript will not have the correct path. To fix this, we can add a publicPath declaration to our Webpack output

module.exports = {
...
    output: {
        filename: '[name].[contenthash].js',
        path: path.resolve(__dirname, 'dist'),
        publicPath: '/dist/'
    },
...
}

We can now perform imports in JS files with the correct path names, such as the following

import image from './img/test.jpg';

const img = document.createElement('img');
img.src = image;
document.querySelector('body').appendChild(img);

ES 6

To transpile our ES6 Code such as arrow functions so that they work in browsers such as Internet Explorer, we can install Babel Loader.

npm install babel-loader @babel/core @babel/preset-env -D 

and then add a rule in our Webpack config

rules: [
    {
      test: /\.m?js$/,
      exclude: /(node_modules|bower_components)/,
      use: {
        loader: 'babel-loader',
        options: {
          presets: ['@babel/preset-env']
        }
      }
    }
  ]
Categories
Uncategorised

Converting a UTF-16 CSV to UTF-8 in PHP

The best solution I’ve found to this is to open the file, and re-write it with the new encoding before opening it for CSV reading;

function get_encoding($filename){
    $encoding='';
    $handle = fopen($filename, 'r');
    $bom = fread($handle, 2);
    //	fclose($handle);
    rewind($handle);

    if($bom === chr(0xff).chr(0xfe)  || $bom === chr(0xfe).chr(0xff)){
        // UTF16 Byte Order Mark present
        $encoding = 'UTF-16';
    } else {
        $file_sample = fread($handle, 1000) + 'e'; //read first 1000 bytes
        // + e is a workaround for mb_string bug
        rewind($handle);

        $encoding = mb_detect_encoding($file_sample , 'UTF-8, UTF-7, ASCII, EUC-JP,SJIS, eucJP-win, SJIS-win, JIS, ISO-2022-JP');
    }
    if ($encoding){
        stream_filter_append($handle, 'convert.iconv.'.$encoding.'/UTF-8');
    }
    return $encoding;
}

/**
* Decode UTF-16 encoded strings.
* 
* Can handle both BOM'ed data and un-BOM'ed data. 
* Assumes Big-Endian byte order if no BOM is available.
* 
* @param   string  $str  UTF-16 encoded data to decode.
* @return  string  UTF-8 / ISO encoded data.
* @access  public
* @version 0.1 / 2005-01-19
* @author  Rasmus Andersson {@link http://rasmusandersson.se/}
* @package Groupies
*/
function utf16_decode($str, &$be=null) {
    if (strlen($str) < 2) {
        return $str;
    }
    $c0 = ord($str{0});
    $c1 = ord($str{1});
    $start = 0;
    if ($c0 == 0xFE && $c1 == 0xFF) {
        $be = true;
        $start = 2;
    } else if ($c0 == 0xFF && $c1 == 0xFE) {
        $start = 2;
        $be = false;
    }
    if ($be === null) {
        $be = true;
    }
    $len = strlen($str);
    $newstr = '';
    for ($i = $start; $i < $len; $i += 2) {
        if ($be) {
            $val = ord($str{$i})   << 4;
            $val += ord($str{$i+1});
        } else {
            $val = ord($str{$i+1}) << 4;
            $val += ord($str{$i});
        }
        $newstr .= ($val == 0x228) ? "\n" : chr($val);
    }
    return $newstr;
}


$newFilename = 'path/to/uploaded/file.scv';
$encoding = get_encoding($newFilename);

/* This is the fix for UTF-16 files which come in from iPad */
if($encoding == 'UTF-16'){
    $utf8Contents = utf16_decode(file_get_contents($newFilename));
    $resource = fopen($newFilename, 'w');
    /* Write the file over the uploaded one */
    fwrite($resource, pack("CCC",0xef,0xbb,0xbf));
    fwrite($resource, $utf8Contents);
}


if (($handle = fopen($newFilename, "r")) !== false) {
    while (($data = fgetcsv($handle)) !== false) {
        ...
    }
}
Categories
Uncategorised

Curling a URL in PHP

Assume the form object contains an array in the form of params

 $fieldString = http_build_query($form->getParams());

//open connection
$ch = curl_init();

//set the url, number of POST vars, POST data
curl_setopt($ch,CURLOPT_URL, $this->_dotMailerUri);
curl_setopt($ch,CURLOPT_POST, count($form->getParams()));
curl_setopt($ch,CURLOPT_POSTFIELDS, $fieldString);
// Set this so the result isn't added to stdout and gets returned instead
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

//execute post
$result = curl_exec($ch);

//close connection
curl_close($ch);
Categories
Uncategorised

Calculating UK Bank Holidays in PHP

This is from the following page at PHP.net: http://php.net/manual/en/ref.calendar.php, copied as a reference here to aid my rapidly depleting hippocampus.

<?php

/*
*    Function to calculate which days are British bank holidays (England & Wales) for a given year.
*
*    Created by David Scourfield, 07 August 2006, and released into the public domain.
*    Anybody may use and/or modify this code.
*
*    USAGE:
*
*    array calculateBankHolidays(int $yr)
*
*    ARGUMENTS
*
*    $yr = 4 digit numeric representation of the year (eg 1997).
*
*    RETURN VALUE
*
*    Returns an array of strings where each string is a date of a bank holiday in the format "yyyy-mm-dd".
*
*    See example below
*
*/

function calculateBankHolidays($yr) {

    $bankHols = [];

    // New year's:
    switch ( date("w", strtotime("$yr-01-01 12:00:00")) ) {
        case 6:
            $bankHols[] = "$yr-01-03";
            break;
        case 0:
            $bankHols[] = "$yr-01-02";
            break;
        default:
            $bankHols[] = "$yr-01-01";
    }

    // Good friday:
    $bankHols[] = date("Y-m-d", strtotime( "+".(easter_days($yr) - 2)." days", strtotime("$yr-03-21 12:00:00") ));

    // Easter Monday:
    $bankHols[] = date("Y-m-d", strtotime( "+".(easter_days($yr) + 1)." days", strtotime("$yr-03-21 12:00:00") ));

    // May Day:
    if ($yr == 1995) {
        $bankHols[] = "1995-05-08"; // VE day 50th anniversary year exception
    } else {
        switch (date("w", strtotime("$yr-05-01 12:00:00"))) {
            case 0:
                $bankHols[] = "$yr-05-02";
                break;
            case 1:
                $bankHols[] = "$yr-05-01";
                break;
            case 2:
                $bankHols[] = "$yr-05-07";
                break;
            case 3:
                $bankHols[] = "$yr-05-06";
                break;
            case 4:
                $bankHols[] = "$yr-05-05";
                break;
            case 5:
                $bankHols[] = "$yr-05-04";
                break;
            case 6:
                $bankHols[] = "$yr-05-03";
                break;
        }
    }

    // Whitsun:
    if ($yr == 2002) { // exception year
        $bankHols[] = "2002-06-03";
        $bankHols[] = "2002-06-04";
    } else {
        switch (date("w", strtotime("$yr-05-31 12:00:00"))) {
            case 0:
                $bankHols[] = "$yr-05-25";
                break;
            case 1:
                $bankHols[] = "$yr-05-31";
                break;
            case 2:
                $bankHols[] = "$yr-05-30";
                break;
            case 3:
                $bankHols[] = "$yr-05-29";
                break;
            case 4:
                $bankHols[] = "$yr-05-28";
                break;
            case 5:
                $bankHols[] = "$yr-05-27";
                break;
            case 6:
                $bankHols[] = "$yr-05-26";
                break;
        }
    }

    // Summer Bank Holiday:
    switch (date("w", strtotime("$yr-08-31 12:00:00"))) {
        case 0:
            $bankHols[] = "$yr-08-25";
            break;
        case 1:
            $bankHols[] = "$yr-08-31";
            break;
        case 2:
            $bankHols[] = "$yr-08-30";
            break;
        case 3:
            $bankHols[] = "$yr-08-29";
            break;
        case 4:
            $bankHols[] = "$yr-08-28";
            break;
        case 5:
            $bankHols[] = "$yr-08-27";
            break;
        case 6:
            $bankHols[] = "$yr-08-26";
            break;
    }

    // Christmas:
    switch ( date("w", strtotime("$yr-12-25 12:00:00")) ) {
        case 5:
            $bankHols[] = "$yr-12-25";
            $bankHols[] = "$yr-12-28";
            break;
        case 6:
            $bankHols[] = "$yr-12-27";
            $bankHols[] = "$yr-12-28";
            break;
        case 0:
            $bankHols[] = "$yr-12-26";
            $bankHols[] = "$yr-12-27";
            break;
        default:
            $bankHols[] = "$yr-12-25";
            $bankHols[] = "$yr-12-26";
    }

    return $bankHols;

}

/*
*    EXAMPLE:
*
*/

header("Content-type: text/plain"); 

$bankHolsThisYear = calculateBankHolidays(2007);

print_r($bankHolsThisYear);

?>

Will output this result:

Array
(
    [0] => 2007-01-01
    [1] => 2007-04-06
    [2] => 2007-04-09
    [3] => 2007-05-07
    [4] => 2007-05-28
    [5] => 2007-08-27
    [6] => 2007-12-25
    [7] => 2007-12-26
)

Thanks to David Scourfield!

Categories
Uncategorised

PHP Regex Snippet: Convert a Title to a Code

This will take out any non-alphanumeric characters and replace them with an underscore

    protected function convertTitleToCode($title)
    {
        return preg_replace("/[^\w]/i", "_", trim(strtolower($title)));
    }
Categories
Uncategorised

Debugging MySQL installed through Homebrew on Yosemite

I recently came across an annoying issue where MySQL would not start on Mac OS X Yosemite, exiting with the following:

ERROR 2002 (HY000): Can&#039;t connect to local MySQL server through socket &#039;/tmp/mysql.sock&#039; (2)

Join me on a journey which makes putting a greased ape on a waltzer and getting him to rate the experience seem like an easy task.

Finding the log files

To fix what’s going wrong, we need to know what’s going wrong. Unfortunately, finding log files (for me at least) can often be a bigger job than fixing the issue at hand. My version of MySQL is installed through Brew. After six days of Googling, I eventually found MySQL’s error log here:

tail -f /usr/local/var/mysql/Daves-MacBook-Pro.local.err

Four and a half days trawling through something which makes War and Peace look like a children’s book, I stumbled on a possible cause for the error:

2015-11-12T15:35:05.354808Z 0 [Warning] InnoDB: Ignoring tablespace `defender/wishlist_item_option` because it could not be opened.

Aha! It looks like one of the databases has become corrupted, MySQL can't open it, and it's failing! Great. Let's try moving the database elsewhere and see how we get on.

ERROR 2002 (HY000): Can&#039;t connect to local MySQL server through socket &#039;/tmp/mysql.sock&#039; (2)

No dice. Right, looking through the log shows up another error:

2015-11-12T15:48:13.051616Z 0 [ERROR] unknown variable &#039;key_buffer=32M&#039;

Variable variables

So, it looks like the variable key_buffer has been replaced with key_buffer_size in a newer version of MySQL. This exists in my MySQL config file:

/usr/local/etc/my.cnf

Changing this sorted my headache, and allowed me to get back to those yummy scrummy databases once more.

Categories
Uncategorised

Flexbox Resources

Vertical Alignment

http://codepen.io/llapgoch/pen/ozbwwx