<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"><channel><title>Miles Johnson</title><link>http://milesj.me</link><description>Recent entries and thoughts</description><language>en-us</language><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/milesj" /><feedburner:info uri="milesj" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:emailServiceId>milesj</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><item><title>Amazon S3 testing in Travis CI</title><link>http://feedproxy.google.com/~r/milesj/~3/3tjFkvpfFpw/amazon-s3-testing-travis-ci</link><guid isPermaLink="false">http://milesj.me/blog/read/amazon-s3-testing-travis-ci</guid><description>&amp;lt;p&amp;gt;I recently started integrating https://travis-ci.org/ into some of my projects. Travis is a continuous integration service that will execute your test cases in multiple different environments. I&amp;#039;ve been putting off integrating &amp;lt;a href=&amp;quot;https://github.com/milesj/Transit&amp;quot;&amp;gt;Transit&amp;lt;/a&amp;gt; into Travis because of Amazon S3 testing, but I found the time to dig into it and implement it successfully.&amp;lt;/p&amp;gt;

&amp;lt;h5&amp;gt;Preparing S3&amp;lt;/h5&amp;gt;

&amp;lt;p&amp;gt;To integrate S3 into Travis, the AWS environment must be prepared. This section can get quite lengthy and complicated, but I will keep it brief and simply. The first step is to create a new bucket and apply a lifecycle rule of 1 day to the entire bucket. This rule will delete all files in the bucket every 24 hours, which in turn requires no maintenance, cleanup and low costs on our end.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;The next step is to create a new IAM group and assign the &amp;quot;Amazon S3 Full Access&amp;quot; policy permission. Once created, we need to modify the policy and change the permissions. I used the following policy for testing, which allows full S3 access to the ci-testing bucket. &amp;lt;/p&amp;gt;

&amp;lt;pre&amp;gt;&amp;lt;code class=&amp;quot;lang-javascript&amp;quot;&amp;gt;{
	&amp;quot;Statement&amp;quot;: [
		{
			&amp;quot;Effect&amp;quot;: &amp;quot;Allow&amp;quot;,
			&amp;quot;Action&amp;quot;: &amp;quot;s3:*&amp;quot;,
			&amp;quot;Resource&amp;quot;: &amp;quot;arn:aws:s3:::ci-testing/*&amp;quot;
		}
	]
}&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;

&amp;lt;p&amp;gt;After the group is setup, create a new user and assign it to the group. Be sure to save/store the credentials (access and secret key) of the user as we will need them later on. It&amp;#039;s also a good idea to set/generate a password for this user.&amp;lt;/p&amp;gt;

&amp;lt;h5&amp;gt;Integrating Travis&amp;lt;/h5&amp;gt;

&amp;lt;p&amp;gt;To make use of S3 in Travis, the appropriate variables must be set in the environment. This can be accomplished using the &amp;lt;code&amp;gt;env:global:&amp;lt;/code&amp;gt; setting in the &amp;lt;code&amp;gt;.travis.yml&amp;lt;/code&amp;gt; file. The region and bucket can be set using plain text.&amp;lt;/p&amp;gt;

&amp;lt;pre&amp;gt;&amp;lt;code class=&amp;quot;lang-yaml&amp;quot;&amp;gt;env:
  global:
    - AWS_S3_REGION=&amp;quot;us-east-1&amp;quot;
    - AWS_S3_BUCKET=&amp;quot;ci-testing&amp;quot;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;

&amp;lt;p&amp;gt;Like any smart developer, the access and secret keys should not be set using plain text, as this would give S3 access to anyone viewing the Travis logs. However, we can still set the private keys using &amp;lt;a href=&amp;quot;http://about.travis-ci.org/docs/user/encryption-keys/&amp;quot;&amp;gt;http://about.travis-ci.org/docs/user/encryption-keys/&amp;lt;/a&amp;gt;. This process requires Ruby and RubyGems to be installed (either with Cygwin, Homebrew or another package manager).&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Installing RubyGems on Cygwin is rather easy. Simply &amp;lt;a href=&amp;quot;http://rubygems.org/pages/download&amp;quot;&amp;gt;download the zip&amp;lt;/a&amp;gt; and extract it to the &amp;lt;code&amp;gt;C:/cygwin/home/&amp;lt;/code&amp;gt; directory. Once extracted, run the following command from within the extracted folder (this requires ruby to be installed via the Cygwin setup).&amp;lt;/p&amp;gt;

&amp;lt;pre&amp;gt;&amp;lt;code class=&amp;quot;lang-bash&amp;quot;&amp;gt;ruby setup.rb&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;

&amp;lt;p&amp;gt;Once installed, install Travis.&amp;lt;/p&amp;gt;

&amp;lt;pre&amp;gt;&amp;lt;code class=&amp;quot;lang-bash&amp;quot;&amp;gt;gem install travis&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;

&amp;lt;p&amp;gt;Then use the &amp;lt;code&amp;gt;encrypt&amp;lt;/code&amp;gt; command coupled with the &amp;lt;code&amp;gt;-r&amp;lt;/code&amp;gt; flag (repository) to generate a secure environment key. In the example, I will be using my Transit repository.&amp;lt;/p&amp;gt;

&amp;lt;pre&amp;gt;&amp;lt;code class=&amp;quot;lang-bash&amp;quot;&amp;gt;travis encrypt -r milesj/Transit AWS_S3_KEY=&amp;quot;&amp;amp;lt;access_key&amp;amp;gt;&amp;quot;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;

&amp;lt;p&amp;gt;Add the encrypted string to the &amp;lt;code&amp;gt;.travis.yml&amp;lt;/code&amp;gt; file. Do the process again for the secret key.&amp;lt;/p&amp;gt;

&amp;lt;pre&amp;gt;&amp;lt;code class=&amp;quot;lang-bash&amp;quot;&amp;gt;travis encrypt -r milesj/Transit AWS_S3_SECRET=&amp;quot;&amp;amp;lt;secret_key&amp;amp;gt;&amp;quot;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;

&amp;lt;p&amp;gt;The file should now look like the following:&amp;lt;/p&amp;gt;

&amp;lt;pre&amp;gt;&amp;lt;code class=&amp;quot;lang-yaml&amp;quot;&amp;gt;env:
  global:
    - AWS_S3_REGION=&amp;quot;us-east-1&amp;quot;
    - AWS_S3_BUCKET=&amp;quot;ci-testing&amp;quot;
    - secure: &amp;quot;&amp;amp;lt;encrypted_access_key&amp;amp;gt;&amp;quot;
    - secure: &amp;quot;&amp;amp;lt;encrypted_secret_key&amp;amp;gt;&amp;quot;&amp;lt;/code&amp;gt;&amp;lt;/pre&amp;gt;

&amp;lt;p&amp;gt;These environment variables can now be accessed from the &amp;lt;code&amp;gt;$_SERVER&amp;lt;/code&amp;gt; global within the test cases. For a full implemented example, check out my &amp;lt;a href=&amp;quot;https://github.com/milesj/Transit&amp;quot;&amp;gt;Transit library&amp;lt;/a&amp;gt;.&amp;lt;/p&amp;gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/milesj?a=3tjFkvpfFpw:kd1eJefKpKw:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/milesj?i=3tjFkvpfFpw:kd1eJefKpKw:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/milesj?a=3tjFkvpfFpw:kd1eJefKpKw:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/milesj?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/milesj?a=3tjFkvpfFpw:kd1eJefKpKw:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/milesj?i=3tjFkvpfFpw:kd1eJefKpKw:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/milesj?a=3tjFkvpfFpw:kd1eJefKpKw:TzevzKxY174"&gt;&lt;img src="http://feeds.feedburner.com/~ff/milesj?d=TzevzKxY174" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/milesj?a=3tjFkvpfFpw:kd1eJefKpKw:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/milesj?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/milesj/~4/3tjFkvpfFpw" height="1" width="1"/&gt;</description><author>Miles Johnson</author><pubDate>Sun, 14 Apr 2013 14:48:35 -0700</pubDate><category>Programming</category><category>PHP</category><category>Code</category><feedburner:origLink>http://milesj.me/blog/read/amazon-s3-testing-travis-ci</feedburner:origLink></item><item><title>Utility v1.4.0</title><link>http://feedproxy.google.com/~r/milesj/~3/Qk75pi7CpeM/changelog-utility-1.4.0</link><guid isPermaLink="false">http://milesj.me/blog/read/changelog-utility-1.4.0</guid><description>&amp;lt;p&amp;gt;A new version of Utility has been released, version &amp;lt;b&amp;gt;1.4.0&amp;lt;/b&amp;gt;. Please &amp;lt;a href=&amp;quot;https://github.com/milesj/Utility/tags&amp;quot;&amp;gt;download the new tag&amp;lt;/a&amp;gt; or &amp;lt;a href=&amp;quot;http://milesj.me/c/19&amp;quot;&amp;gt;view the documentation&amp;lt;/a&amp;gt;. If you have any questions, be sure to send me an email or comment on this post. If you run into any problems, be sure to report an issue on the Github repository.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;Version:&amp;lt;/b&amp;gt; 1.4.0&amp;lt;br&amp;gt;
&amp;lt;b&amp;gt;Tested On:&amp;lt;/b&amp;gt; PHP 5.3.13, CakePHP 2.3.1, Composer&amp;lt;br&amp;gt;
&amp;lt;b&amp;gt;Requires:&amp;lt;/b&amp;gt; PHP 5.3, CakePHP 2, Composer&amp;lt;br&amp;gt;
&amp;lt;b&amp;gt;Commit Hash:&amp;lt;/b&amp;gt; &amp;lt;a href=&amp;quot;https://github.com/milesj/Utility/commit/b109b71a2d05e7b044d702c124f9faa4c4bb5771&amp;quot;&amp;gt;b109b71a2d05e7b044d702c124f9faa4c4bb5771&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;
&amp;lt;b&amp;gt;Changes:&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;ul class=&amp;quot;list&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;Added a BaseInstallShell and BaseUpgradeShell to handle plugin installs/upgrades&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Added the SluggableBehavior instance as a second argument to the beforeSlug() and afterSlug() callbacks&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Added a unique option to SluggableBehavior&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Added append() and prepend() to BreadcrumbHelper&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Added getCount as primary caching method in CacheableBehavior&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Added default rule messaging fallbacks to ValidateableBehavior&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Added getAll(), getList(), getCount(), getById() and getBySlug() to CacheableBehavior which can be called from the Model layer&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Added Decoda configuration to Configure via plugin bootstrap&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Added UtilityHelper to handle all purpose view functionality&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Fixed a bug with SluggableBehavior wildcard behaving incorrectly&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Fixed a bug where HTML is not stripped from breadcrumbs&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Updated AutoLoginComponent to use the referrer as the auth login redirect&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Updated SluggableBehavior to not sluggify a record if the slug is manually set in the data&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Updated ValidateableBehavior to grab $validate and use as the default validation set&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Updated EnumerableBehavior format setting to be APPEND by default instead of REPLACE&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Updated Decoda to v6.0.0&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/milesj?a=Qk75pi7CpeM:Sap_JmznmO8:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/milesj?i=Qk75pi7CpeM:Sap_JmznmO8:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/milesj?a=Qk75pi7CpeM:Sap_JmznmO8:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/milesj?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/milesj?a=Qk75pi7CpeM:Sap_JmznmO8:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/milesj?i=Qk75pi7CpeM:Sap_JmznmO8:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/milesj?a=Qk75pi7CpeM:Sap_JmznmO8:TzevzKxY174"&gt;&lt;img src="http://feeds.feedburner.com/~ff/milesj?d=TzevzKxY174" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/milesj?a=Qk75pi7CpeM:Sap_JmznmO8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/milesj?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/milesj/~4/Qk75pi7CpeM" height="1" width="1"/&gt;</description><author>Miles Johnson</author><pubDate>Mon, 08 Apr 2013 16:07:50 -0700</pubDate><category>CakePHP</category><feedburner:origLink>http://milesj.me/blog/read/changelog-utility-1.4.0</feedburner:origLink></item><item><title>Decoda v6.0.0</title><link>http://feedproxy.google.com/~r/milesj/~3/AwnUrG1uadE/changelog-decoda-6.0.0</link><guid isPermaLink="false">http://milesj.me/blog/read/changelog-decoda-6.0.0</guid><description>&amp;lt;p&amp;gt;A new version of Decoda has been released, version &amp;lt;b&amp;gt;6.0.0&amp;lt;/b&amp;gt;. Please &amp;lt;a href=&amp;quot;https://github.com/milesj/Decoda/tags&amp;quot;&amp;gt;download the new tag&amp;lt;/a&amp;gt; or &amp;lt;a href=&amp;quot;http://milesj.me/c/6&amp;quot;&amp;gt;view the documentation&amp;lt;/a&amp;gt;. If you have any questions, be sure to send me an email or comment on this post. If you run into any problems, be sure to report an issue on the Github repository.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;Version:&amp;lt;/b&amp;gt; 6.0.0&amp;lt;br&amp;gt;
&amp;lt;b&amp;gt;Tested On:&amp;lt;/b&amp;gt; PHP 5.3.13, Composer&amp;lt;br&amp;gt;
&amp;lt;b&amp;gt;Requires:&amp;lt;/b&amp;gt; PHP 5.3, Composer&amp;lt;br&amp;gt;
&amp;lt;b&amp;gt;Commit Hash:&amp;lt;/b&amp;gt; &amp;lt;a href=&amp;quot;https://github.com/milesj/Decoda/commit/70a679488d2be76c8f997f7bdcc0555871e7bfe2&amp;quot;&amp;gt;70a679488d2be76c8f997f7bdcc0555871e7bfe2&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;
&amp;lt;b&amp;gt;Changes:&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;ul class=&amp;quot;list&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;Added a Component class which all Filters, Hooks, Engines and Loaders extend&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Added a Loader class to handle resource file loading for configuration and messages&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Added Hook::startup() to initialize data before callbacks are called&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Added Decoda::addMessages() to add messages using a Loader&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Added Decoda::getBlacklist() and getWhitelist()&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Added a 2nd argument $key for Decoda::addFilter() and addHook()&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Added a default attribute to ImageFilter (img=&amp;quot;200x200&amp;quot;)&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Added a default attribute to ListFilter (list=&amp;quot;upper-roman&amp;quot;)&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Added a new TableFilter&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Added custom exceptions&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Renamed all config methods to getConfig() and setConfig()&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Renamed Filter::tag() to getTag()&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Renamed Filter::tags() to getTags()&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Renamed Engine::setPath() to addPath()&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Renamed Engine::getPath() to getPaths()&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Updated CensorHook to support blacklisting words using a Loader&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Updated EmoticonHook to support adding emoticons using a Loader&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Updated Decoda::setLocale() so that it no longer throws exceptions (can now support setting the default locale)&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Updated Engines to support multiple template lookup paths&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Updated with Travis CI and phpunit.xml integration&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/milesj?a=AwnUrG1uadE:ea29qrYReqM:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/milesj?i=AwnUrG1uadE:ea29qrYReqM:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/milesj?a=AwnUrG1uadE:ea29qrYReqM:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/milesj?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/milesj?a=AwnUrG1uadE:ea29qrYReqM:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/milesj?i=AwnUrG1uadE:ea29qrYReqM:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/milesj?a=AwnUrG1uadE:ea29qrYReqM:TzevzKxY174"&gt;&lt;img src="http://feeds.feedburner.com/~ff/milesj?d=TzevzKxY174" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/milesj?a=AwnUrG1uadE:ea29qrYReqM:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/milesj?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/milesj/~4/AwnUrG1uadE" height="1" width="1"/&gt;</description><author>Miles Johnson</author><pubDate>Fri, 05 Apr 2013 00:26:31 -0700</pubDate><category>PHP</category><feedburner:origLink>http://milesj.me/blog/read/changelog-decoda-6.0.0</feedburner:origLink></item><item><title>Important uploader changes</title><link>http://feedproxy.google.com/~r/milesj/~3/jGJts3T1Io0/important-uploader-changes</link><guid isPermaLink="false">http://milesj.me/blog/read/important-uploader-changes</guid><description>&amp;lt;p&amp;gt;There are a few &amp;lt;a href=&amp;quot;http://milesj.me/code/cakephp/uploader&amp;quot;&amp;gt;Uploader&amp;lt;/a&amp;gt; changes that I made this week that everyone should be aware of. Simple change logs will not suffice, so I will briefly talk about the changes.&amp;lt;/p&amp;gt;

&amp;lt;h5&amp;gt;Why not a minor version upgrade?&amp;lt;/h5&amp;gt;

&amp;lt;p&amp;gt;You&amp;#039;re right, it should be a minor version instead of a patch. I was trying to be hasty and screwed that up and now it&amp;#039;s too late. This post is also to warn anyone updating via Composer without checking the changes.&amp;lt;/p&amp;gt;

&amp;lt;h5&amp;gt;Amazon S3 endpoints&amp;lt;/h5&amp;gt;

&amp;lt;p&amp;gt;Last week Amazon changed their AWS SDK and in the process broke the S3 URLs (endpoints) that are generated via the Uploader and Transit. &amp;lt;a href=&amp;quot;https://github.com/milesj/Transit/commit/adf2e8a2d99d027001783f2d5bed5e00e88945e4&amp;quot;&amp;gt;I quickly fixed this once it was brought to my attention&amp;lt;/a&amp;gt;, however, if anyone was uploading files during this time frame, the S3 transport would of failed and will continue to fail until Transit is updated.&amp;lt;/p&amp;gt;

&amp;lt;h5&amp;gt;Imported file validation&amp;lt;/h5&amp;gt;

&amp;lt;p&amp;gt;File validation up to this point was only for literal file uploads and not imports. &amp;lt;a href=&amp;quot;https://github.com/milesj/Uploader/commit/c9875af9d9d2ec2bebc8f10c1738bdc8a424a70b&amp;quot;&amp;gt;After many requests I decided to add file validation to importing files&amp;lt;/a&amp;gt;. The process and configuration should be the same for both uploads and imports. &amp;lt;a href=&amp;quot;https://github.com/milesj/Transit/commit/c70c37a30527634ae467b2bd8554d1d6943fbc6f&amp;quot;&amp;gt;I also updated Transit to import files under https&amp;lt;/a&amp;gt;.&amp;lt;/p&amp;gt;

&amp;lt;h5&amp;gt;Extension detection&amp;lt;/h5&amp;gt;

&amp;lt;p&amp;gt;In the past, the extension of a file was determined by the ending characters in the literal filename. This was changed and it will now determine the extension &amp;lt;a href=&amp;quot;https://github.com/milesj/Transit/commit/8ab83df582d1fe8c91d9fc671145ae690685d172&amp;quot;&amp;gt;based off the files mime type&amp;lt;/a&amp;gt; (image/jpeg = jpg, etc). This provides support for files that do not have extensions, but are true files (primarily applies to URLs).&amp;lt;/p&amp;gt;

&amp;lt;h5&amp;gt;Swapped type/mimeType validation rules&amp;lt;/h5&amp;gt;

&amp;lt;p&amp;gt;These 2 validation rules continue to confuse people, and it confused me also as the terminology is backwards. I decided to swap the functionality of these, which in turn &amp;lt;u&amp;gt;will break backwards compatibility&amp;lt;/u&amp;gt;. The way these should work is as so: &amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;If type equals &amp;quot;image&amp;quot; then all image mime types will pass (image/jpeg, image/png, etc). This allows for easy validation of all images instead of defining mime types for each one. The type value can be anything before the / in the mime type declarations.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;As for mimeType, this should equate to the literal mime type value: image/png, text/html, audio/mp3, etc.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;I may combine these into a single validation rule to remove the confusion that they cause.&amp;lt;/p&amp;gt;

&amp;lt;h5&amp;gt;Upgrade now!&amp;lt;/h5&amp;gt;

&amp;lt;p&amp;gt;Please update to Uploader v4.0.9 and Transit v1.0.7 immediately, especially if you are using Amazon S3.&amp;lt;/p&amp;gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/milesj?a=jGJts3T1Io0:ZV3FthpLjq0:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/milesj?i=jGJts3T1Io0:ZV3FthpLjq0:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/milesj?a=jGJts3T1Io0:ZV3FthpLjq0:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/milesj?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/milesj?a=jGJts3T1Io0:ZV3FthpLjq0:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/milesj?i=jGJts3T1Io0:ZV3FthpLjq0:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/milesj?a=jGJts3T1Io0:ZV3FthpLjq0:TzevzKxY174"&gt;&lt;img src="http://feeds.feedburner.com/~ff/milesj?d=TzevzKxY174" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/milesj?a=jGJts3T1Io0:ZV3FthpLjq0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/milesj?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/milesj/~4/jGJts3T1Io0" height="1" width="1"/&gt;</description><author>Miles Johnson</author><pubDate>Wed, 20 Mar 2013 22:48:53 -0700</pubDate><category>CakePHP</category><feedburner:origLink>http://milesj.me/blog/read/important-uploader-changes</feedburner:origLink></item><item><title>Down the admin pipeline</title><link>http://feedproxy.google.com/~r/milesj/~3/d98T3txn15A/down-the-admin-pipeline</link><guid isPermaLink="false">http://milesj.me/blog/read/down-the-admin-pipeline</guid><description>&amp;lt;p&amp;gt;Nearly 2 weeks ago I talked briefly about &amp;lt;a href=&amp;quot;http://milesj.me/blog/read/everyone-needs-admin&amp;quot;&amp;gt;the CakePHP admin plugin&amp;lt;/a&amp;gt; I was building. Since then I have tagged 10 minor versions with many new features and bug fixes. I spent a good chunk of my time testing the admin against my current applications and attempting to fix any issues. I can only do so much testing by myself, so if any of you end up testing the plugin, I would greatly appreciate some feedback!&amp;lt;/p&amp;gt;

&amp;lt;h5&amp;gt;Models overview&amp;lt;/h5&amp;gt;

&amp;lt;p&amp;gt;While testing the admin against my applications, I noticed many models were missing display fields and associations. I figured an overview table of all model properties would be a great feature to include.&amp;lt;/p&amp;gt;

&amp;lt;div class=&amp;quot;align-center&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;http://milesj.me/img/admin/models.jpg&amp;quot;&amp;gt;&amp;lt;img width=&amp;quot;250&amp;quot; src=&amp;quot;http://milesj.me/img/admin/models.jpg&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/div&amp;gt;

&amp;lt;h5&amp;gt;Configuration overview&amp;lt;/h5&amp;gt;

&amp;lt;p&amp;gt;Hot on the heels of the models overview, I decided to apply the same treatment to CakePHPs configuration. This page will display all the top-level configuration settings in neatly structured tables and columns.&amp;lt;/p&amp;gt;

&amp;lt;div class=&amp;quot;align-center&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;http://milesj.me/img/admin/config.jpg&amp;quot;&amp;gt;&amp;lt;img width=&amp;quot;250&amp;quot; src=&amp;quot;http://milesj.me/img/admin/config.jpg&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/div&amp;gt;

&amp;lt;h5&amp;gt;Action logging and syslog overview&amp;lt;/h5&amp;gt;

&amp;lt;p&amp;gt;Any sane admin system would log an administrators actions, because you know, just in case they do something shady! The admin plugin comes enabled with a logging system that tracks all users actions. This feature can be enabled (default) or disabled through Configure. To manually log something, one can use the AdminToolbarComponent::logAction() method.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;If you are like me, you get tired of SSHing into your server and checking the logs, or are too lazy to setup Splunk or Logstash. Because of this I added a simple log parsing feature that aggregates exceptions and displays them in a pretty table. Do note that this is basic parsing and shouldn&amp;#039;t be heavily relied on, and will only parse logs under 2MB.&amp;lt;/p&amp;gt;

&amp;lt;div class=&amp;quot;align-center&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;http://milesj.me/img/admin/logs-1.jpg&amp;quot;&amp;gt;&amp;lt;img width=&amp;quot;250&amp;quot; src=&amp;quot;http://milesj.me/img/admin/logs-1.jpg&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt;&amp;lt;/a&amp;gt; &amp;lt;a href=&amp;quot;http://milesj.me/img/admin/logs-2.jpg&amp;quot;&amp;gt;&amp;lt;img width=&amp;quot;250&amp;quot; src=&amp;quot;http://milesj.me/img/admin/logs-2.jpg&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/div&amp;gt;

&amp;lt;h5&amp;gt;Reported content&amp;lt;/h5&amp;gt;

&amp;lt;p&amp;gt;Another useful feature that many sites utilize is a content reporting/flagging system. My forum plugin utilizes one, my tournament plugin will, and my applications do. Each of them rolled their own system, so I thought it would be easier to roll this feature into the admin and have them all extend from it.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Every user can report content (a model record) and organize it under a specific type (sexual, offensive, etc). These pending reports will then appear in the reports section of the admin until they are resolved by an administrator. For ease of use, the AdminToolbarComponent::reportItem() method can be used within the application context.&amp;lt;/p&amp;gt;

&amp;lt;div class=&amp;quot;align-center&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;http://milesj.me/img/admin/reports-1.jpg&amp;quot;&amp;gt;&amp;lt;img width=&amp;quot;250&amp;quot; src=&amp;quot;http://milesj.me/img/admin/reports-1.jpg&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt;&amp;lt;/a&amp;gt; &amp;lt;a href=&amp;quot;http://milesj.me/img/admin/reports-2.jpg&amp;quot;&amp;gt;&amp;lt;img width=&amp;quot;250&amp;quot; src=&amp;quot;http://milesj.me/img/admin/reports-2.jpg&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/div&amp;gt;

&amp;lt;h5&amp;gt;Model and behavior callbacks&amp;lt;/h5&amp;gt;

&amp;lt;p&amp;gt;Another nifty feature is the ability to configure model and behavior callbacks that can be triggered from the index listing (behavior) or the read page (model). This allows behavior methods like TreeBehavior::reorder() and CacheableBehavior::clearCache() to be executed within the admin. As for models, it allows custom methods like User::ban($id) to also be executed from within the admin (and is also used in reports).&amp;lt;/p&amp;gt;

&amp;lt;div class=&amp;quot;align-center&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;http://milesj.me/img/admin/process-1.jpg&amp;quot;&amp;gt;&amp;lt;img width=&amp;quot;250&amp;quot; src=&amp;quot;http://milesj.me/img/admin/process-1.jpg&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt;&amp;lt;/a&amp;gt; &amp;lt;a href=&amp;quot;http://milesj.me/img/admin/process-2.jpg&amp;quot;&amp;gt;&amp;lt;img width=&amp;quot;250&amp;quot; src=&amp;quot;http://milesj.me/img/admin/process-2.jpg&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/div&amp;gt;

&amp;lt;h5&amp;gt;Filters&amp;lt;/h5&amp;gt;

&amp;lt;p&amp;gt;What kind of system would this be if you couldn&amp;#039;t filter results? A crappy one! Good thing this plugin is amazing. The index page now supports filtering (via named params) and pagination in unison. The filter fields are determined from the models schema and work in a similar fashion to the create and update pages. &amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Integer and date fields provide a comparison dropdown that lets you choose the operator to use: less than, not equals, etc. Dates allow for any kind of input and will be strtotime()d on the backend. Enumerables, booleans and belongs to relations will be represented as a dropdown. Strings will result in a LIKE %% query. Any active filter will be highlighted in yellow.&amp;lt;/p&amp;gt;

&amp;lt;div class=&amp;quot;align-center&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;http://milesj.me/img/admin/filters-1.jpg&amp;quot;&amp;gt;&amp;lt;img width=&amp;quot;250&amp;quot; src=&amp;quot;http://milesj.me/img/admin/filters-1.jpg&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt;&amp;lt;/a&amp;gt; &amp;lt;a href=&amp;quot;http://milesj.me/img/admin/filters-2.jpg&amp;quot;&amp;gt;&amp;lt;img width=&amp;quot;250&amp;quot; src=&amp;quot;http://milesj.me/img/admin/filters-2.jpg&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/div&amp;gt;

&amp;lt;h5&amp;gt;Well this is cool and all...&amp;lt;/h5&amp;gt;

&amp;lt;p&amp;gt;Don&amp;#039;t forget all the custom model icons, and the localization support, and the table action buttons, and yeah, many more things. I have a long list of features to still add, so stick around!&amp;lt;/p&amp;gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/milesj?a=d98T3txn15A:9hxSjQXIQcM:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/milesj?i=d98T3txn15A:9hxSjQXIQcM:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/milesj?a=d98T3txn15A:9hxSjQXIQcM:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/milesj?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/milesj?a=d98T3txn15A:9hxSjQXIQcM:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/milesj?i=d98T3txn15A:9hxSjQXIQcM:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/milesj?a=d98T3txn15A:9hxSjQXIQcM:TzevzKxY174"&gt;&lt;img src="http://feeds.feedburner.com/~ff/milesj?d=TzevzKxY174" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/milesj?a=d98T3txn15A:9hxSjQXIQcM:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/milesj?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/milesj/~4/d98T3txn15A" height="1" width="1"/&gt;</description><author>Miles Johnson</author><pubDate>Wed, 20 Mar 2013 01:00:40 -0700</pubDate><category>CakePHP</category><category>Plugins</category><feedburner:origLink>http://milesj.me/blog/read/down-the-admin-pipeline</feedburner:origLink></item><item><title>Because everyone needs an admin</title><link>http://feedproxy.google.com/~r/milesj/~3/g0LpTkhMiw4/everyone-needs-admin</link><guid isPermaLink="false">http://milesj.me/blog/read/everyone-needs-admin</guid><description>&amp;lt;p&amp;gt;If you are like me, you hate building administration panels. They either take the same length of development, or more, compared to the actual application. On top of that, you end up re-building an admin interface for every application. So... much... effort... &amp;lt;code&amp;gt;I&amp;#039;m just too lazy&amp;lt;/code&amp;gt;. Out of 3 personal applications that I have running live, none of them have an admin interface (Yay for raw MySQL!). I think it&amp;#039;s about time I solve this problem by creating an all-purpose CRUD plugin that can be dropped into any application. I looked &amp;lt;a href=&amp;quot;https://github.com/Pollenizer/CakePHP-Admin-Plugin&amp;quot;&amp;gt;around&amp;lt;/a&amp;gt; &amp;lt;a href=&amp;quot;https://github.com/gerhardsletten/Active-Admin-CakePHP&amp;quot;&amp;gt;at other&amp;lt;/a&amp;gt; &amp;lt;a href=&amp;quot;https://github.com/nicolasramy/CakePHPBootstrapAdmin&amp;quot;&amp;gt;plugins&amp;lt;/a&amp;gt;, but none of them offered what I wanted; even CakePHP scaffolding, &amp;lt;a href=&amp;quot;http://browniephp.org/&amp;quot;&amp;gt;BrowniePHP&amp;lt;/a&amp;gt; and &amp;lt;a href=&amp;quot;http://croogo.org/&amp;quot;&amp;gt;Croogo&amp;lt;/a&amp;gt; fell short. I only had 3 hard requirements:&amp;lt;/p&amp;gt;

&amp;lt;ul class=&amp;quot;list&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;No manual installation (creating controllers, views, etc)&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;CRUD mapping for every model (including plugins)&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;ACL, authentication and authorization&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;


&amp;lt;p&amp;gt;So with no viable option, I went ahead and built this plugin over the past week, aptly named &amp;lt;a href=&amp;quot;https://github.com/milesj/Admin&amp;quot;&amp;gt;Admin&amp;lt;/a&amp;gt;. The plugin meets all the requirements I listed above and then some. Let me take you on a wonderful tour of its features and functionality. In my quick little demonstration, I will be using a test application that also uses the Forum and Tournament plugins that I wrote.&amp;lt;/p&amp;gt;

&amp;lt;h5&amp;gt;Everyone loves dashboards&amp;lt;/h5&amp;gt;

&amp;lt;p&amp;gt;To keep things simple, I tried not to clutter the layout. The design and layout implement &amp;lt;a href=&amp;quot;http://twitter.github.com/bootstrap/index.html&amp;quot;&amp;gt;Twitter Bootstrap&amp;lt;/a&amp;gt;, along with its responsive styles and jQuery components. &amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;The admin dashboard and navigation simply list out all enabled plugins and their models. Models need to be installed from the shell before CRUD can be enabled. If a model is not installed, a red warning will appear and exceptions will be thrown when trying to navigate around.&amp;lt;/p&amp;gt;

&amp;lt;div class=&amp;quot;align-center&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;http://milesj.me/img/admin/dashboard.jpg&amp;quot;&amp;gt;&amp;lt;img width=&amp;quot;250&amp;quot; src=&amp;quot;http://milesj.me/img/admin/dashboard.jpg&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/div&amp;gt;

&amp;lt;p&amp;gt;The index of every model will list out and paginate all records (duh). The records will also fetch and display belongsTo fields by utilizing the models display fields and primary keys. If your models inherit &amp;lt;a href=&amp;quot;https://github.com/milesj/Utility&amp;quot;&amp;gt;Utility.Enumerable&amp;lt;/a&amp;gt;, their values will seamlessly be replaced by their enumerable equivalent (the same applies to forms).&amp;lt;/p&amp;gt;

&amp;lt;div class=&amp;quot;align-center&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;http://milesj.me/img/admin/index.jpg&amp;quot;&amp;gt;&amp;lt;img width=&amp;quot;250&amp;quot; src=&amp;quot;http://milesj.me/img/admin/index.jpg&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/div&amp;gt;

&amp;lt;h5&amp;gt;CRUD is the staple of any admin&amp;lt;/h5&amp;gt;

&amp;lt;p&amp;gt;Wouldn&amp;#039;t you agree? That&amp;#039;s why the plugin supports moderate CRUD functionality for all models, including plugins, right of the box (not really, but requires minor installation). No controllers are needed as every model is URL routed and mapped allowing quick development. The system relies heavily on a models property definitions (display field, primary keys, associations, database schema, etc) to generate and provide strict functionality. CRUD also makes use of ACL allowing users and groups specific access.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;The create and update pages work in a similar fashion. Every form has functionality derived from the models validation rules, database schema and associations. This allows for input fields to set requirements, null checks and more. Any &amp;lt;code&amp;gt;belongsTo&amp;lt;/code&amp;gt; field is represented as a drop down list or a type ahead field (depending on how many records exist in the database). Forms also provide minor support for &amp;lt;code&amp;gt;hasAndBelongsToMany&amp;lt;/code&amp;gt; relations.&amp;lt;/p&amp;gt;

&amp;lt;div class=&amp;quot;align-center&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;http://milesj.me/img/admin/create.jpg&amp;quot;&amp;gt;&amp;lt;img width=&amp;quot;250&amp;quot; src=&amp;quot;http://milesj.me/img/admin/create.jpg&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;a href=&amp;quot;http://milesj.me/img/admin/update.jpg&amp;quot;&amp;gt;&amp;lt;img width=&amp;quot;250&amp;quot; src=&amp;quot;http://milesj.me/img/admin/update.jpg&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/div&amp;gt;

&amp;lt;p&amp;gt;The read page provides an overview of a record including full associated data. Be careful as this page will pull in &amp;lt;code&amp;gt;all data&amp;lt;/code&amp;gt; unless limits and conditions are placed.&amp;lt;/p&amp;gt;

&amp;lt;div class=&amp;quot;align-center&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;http://milesj.me/img/admin/read-1.jpg&amp;quot;&amp;gt;&amp;lt;img width=&amp;quot;250&amp;quot; src=&amp;quot;http://milesj.me/img/admin/read-1.jpg&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;a href=&amp;quot;http://milesj.me/img/admin/read-2.jpg&amp;quot;&amp;gt;&amp;lt;img width=&amp;quot;250&amp;quot; src=&amp;quot;http://milesj.me/img/admin/read-2.jpg&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/div&amp;gt;

&amp;lt;p&amp;gt;And finally the delete page, which provides a confirmation of deletion (because everyone hates accidental deletions). The confirmation also displays a nested list of dependent associated records that will also be deleted.&amp;lt;/p&amp;gt;

&amp;lt;div class=&amp;quot;align-center&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;http://milesj.me/img/admin/delete.jpg&amp;quot;&amp;gt;&amp;lt;img width=&amp;quot;250&amp;quot; src=&amp;quot;http://milesj.me/img/admin/delete.jpg&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/div&amp;gt;

&amp;lt;h5&amp;gt;Access control lists, really?&amp;lt;/h5&amp;gt;

&amp;lt;p&amp;gt;No one ever uses the ACL system, why? Because it&amp;#039;s complicated and hard to learn. I would always steer away from using CakePHP&amp;#039;s ACL, but after diving into it, I must say that it is very powerful if used right (and here&amp;#039;s to hoping I am). The ACL supports AROs (basically users, groups and roles), ACOs (objects to administer) and permissions (CRUD access). The plugin makes heavy use of defining ACOs for every model and setting up ARO permissions to enable or disable CRUD functionality.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;The plugin also generates an ACL matrix which displays an overview of CRUD permissions for AROs (vertical columns) and ACOs (horizontal columns). Each of the 4 boxes represent an action: create, read, update and delete. Each color represents permission: green has access, red does not, while blue inherits from parent.&amp;lt;/p&amp;gt;

&amp;lt;div class=&amp;quot;align-center&amp;quot;&amp;gt;&amp;lt;a href=&amp;quot;http://milesj.me/img/admin/acl.jpg&amp;quot;&amp;gt;&amp;lt;img width=&amp;quot;250&amp;quot; src=&amp;quot;http://milesj.me/img/admin/acl.jpg&amp;quot; alt=&amp;quot;&amp;quot;&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/div&amp;gt;

&amp;lt;p&amp;gt;To integrate ACL into the admin plugin, custom models were created. They are RequestObject (extends Aro), ControlObject (extends Aco) and ObjectPermission (extends Permission).&amp;lt;/p&amp;gt;

&amp;lt;h5&amp;gt;This looks outstanding, what else is down the pipeline?&amp;lt;/h5&amp;gt;

&amp;lt;p&amp;gt;Since this is a very early alpha preview, much more will come of this plugin. Since the features are too awesome to describe, I will just list a few.&amp;lt;/p&amp;gt;

&amp;lt;ul class=&amp;quot;list&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;Custom icons for each model/plugin&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Overrides for controller and view CRUD&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Filtering and searching&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Improved support for behaviors like Tree&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Logging of administrator actions&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;


&amp;lt;p&amp;gt;I would really love some feedback and suggestions on this. Do note that since this is in alpha, the plugin is &amp;lt;b&amp;gt;not&amp;lt;/b&amp;gt; production ready, and as such should be installed using a dev minimum-stability in Composer.&amp;lt;/p&amp;gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/milesj?a=g0LpTkhMiw4:jyXQ5Wez-q0:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/milesj?i=g0LpTkhMiw4:jyXQ5Wez-q0:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/milesj?a=g0LpTkhMiw4:jyXQ5Wez-q0:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/milesj?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/milesj?a=g0LpTkhMiw4:jyXQ5Wez-q0:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/milesj?i=g0LpTkhMiw4:jyXQ5Wez-q0:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/milesj?a=g0LpTkhMiw4:jyXQ5Wez-q0:TzevzKxY174"&gt;&lt;img src="http://feeds.feedburner.com/~ff/milesj?d=TzevzKxY174" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/milesj?a=g0LpTkhMiw4:jyXQ5Wez-q0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/milesj?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/milesj/~4/g0LpTkhMiw4" height="1" width="1"/&gt;</description><author>Miles Johnson</author><pubDate>Thu, 07 Mar 2013 23:39:01 -0800</pubDate><category>CakePHP</category><category>Plugins</category><feedburner:origLink>http://milesj.me/blog/read/everyone-needs-admin</feedburner:origLink></item><item><title>Forum v3.3.0</title><link>http://feedproxy.google.com/~r/milesj/~3/H4BBagJhw10/changelog-forum-3.3.0</link><guid isPermaLink="false">http://milesj.me/blog/read/changelog-forum-3.3.0</guid><description>&amp;lt;p&amp;gt;A new version of Forum has been released, version &amp;lt;b&amp;gt;3.3.0&amp;lt;/b&amp;gt;. Please &amp;lt;a href=&amp;quot;https://github.com/milesj/Forum/tags&amp;quot;&amp;gt;download the new tag&amp;lt;/a&amp;gt; or &amp;lt;a href=&amp;quot;http://milesj.me/c/13&amp;quot;&amp;gt;view the documentation&amp;lt;/a&amp;gt;. If you have any questions, be sure to send me an email or comment on this post. If you run into any problems, be sure to report an issue on the Github repository.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;Version:&amp;lt;/b&amp;gt; 3.3.0&amp;lt;br&amp;gt;
&amp;lt;b&amp;gt;Tested On:&amp;lt;/b&amp;gt; PHP 5.4.3, CakePHP 2.3.0, Composer&amp;lt;br&amp;gt;
&amp;lt;b&amp;gt;Requires:&amp;lt;/b&amp;gt; PHP 5.3, CakePHP 2, Composer&amp;lt;br&amp;gt;
&amp;lt;b&amp;gt;Commit Hash:&amp;lt;/b&amp;gt; &amp;lt;a href=&amp;quot;https://github.com/milesj/Forum/commit/3fbe1526b2be48402c15ee67541306252d0fc992&amp;quot;&amp;gt;3fbe1526b2be48402c15ee67541306252d0fc992&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;
&amp;lt;b&amp;gt;Changes:&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;ul class=&amp;quot;list&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;Requires PHP 5.3 and Composer&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Upgraded Utility plugin to 1.3.x&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Upgraded Decoda to 5.x&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Added FORUM_DATABASE and FORUM_PREFIX constants&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Added avatar mapping support in Forum.userMap.avatar&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Added support for layout overrides through Forum.viewLayout&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Updated shells, models and controllers to use the new FORUM_* constants&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Updated to HTML5 doctype&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Fixed localization not changing&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Fixed search not working for guests &amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Replaced jQuery with Mootools&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Replaced Markitup with Decoda&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Replaced database settings with Forum.settings and Configure&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Renamed CommonHelper to ForumHelper&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Renamed settings to be camelCase&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Moved around search and login forms&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Lots of polish and fixes&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/milesj?a=H4BBagJhw10:Aek-LEw91LI:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/milesj?i=H4BBagJhw10:Aek-LEw91LI:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/milesj?a=H4BBagJhw10:Aek-LEw91LI:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/milesj?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/milesj?a=H4BBagJhw10:Aek-LEw91LI:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/milesj?i=H4BBagJhw10:Aek-LEw91LI:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/milesj?a=H4BBagJhw10:Aek-LEw91LI:TzevzKxY174"&gt;&lt;img src="http://feeds.feedburner.com/~ff/milesj?d=TzevzKxY174" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/milesj?a=H4BBagJhw10:Aek-LEw91LI:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/milesj?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/milesj/~4/H4BBagJhw10" height="1" width="1"/&gt;</description><author>Miles Johnson</author><pubDate>Tue, 29 Jan 2013 19:00:12 -0800</pubDate><category>CakePHP</category><feedburner:origLink>http://milesj.me/blog/read/changelog-forum-3.3.0</feedburner:origLink></item><item><title>Repository Cleanup</title><link>http://feedproxy.google.com/~r/milesj/~3/_PxlFv0Zu1Q/repository-cleanup</link><guid isPermaLink="false">http://milesj.me/blog/read/repository-cleanup</guid><description>&amp;lt;p&amp;gt;I&amp;#039;m currently in the mood to cleanup all my Github repositories, and with this will come some changes. I am posting this to give a warning to anyone who is cloning my repositories either directly or via submodule, as some of the repository names (and URLs) will change. This overhaul is meant to free up some of my time as I plan to veer away from starting any new projects (unless it&amp;#039;s part of a client request) and merely want to support my current projects with bug fixes and new features, if any. With this change, the following changes are happening:&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;The following projects will have their &amp;lt;b&amp;gt;names changed&amp;lt;/b&amp;gt;:&amp;lt;br&amp;gt;
&amp;lt;ul class=&amp;quot;list&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;php-decoda --&amp;amp;gt; Decoda&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;php-transit --&amp;amp;gt; Transit&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;php-packager --&amp;amp;gt; Packager&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;cakephp-utility --&amp;amp;gt; Utility&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;cakephp-forum --&amp;amp;gt; Forum&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;cakephp-uploader --&amp;amp;gt; Uploader&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;moo-decoda --&amp;amp;gt; Decoda.js&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;


&amp;lt;p&amp;gt;The following projects will &amp;lt;b&amp;gt;be deprecated&amp;lt;/b&amp;gt; and no longer receive any kind of support: &amp;lt;code&amp;gt;cake-decoda, cake-ajax_handler, cake-auto_login, cake-cache_kill, cake-feeds, cake-spam_blocker, cake-redirect_route, cake-we_game, php-type_converter, php-statsburner&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Most of the deprecated projects were moved to the Utility plugin or the Titon project and will continue to receive support there. The stand alone projects are merely deprecated.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;The following projects will &amp;lt;b&amp;gt;no longer be supported&amp;lt;/b&amp;gt; excluding critical bugs: &amp;lt;code&amp;gt;php-compression, php-resession, php-numword, php-gears, php-formation, php-databasic&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Thanks for all your continuing support and sorry if these minor changes cause any hiccups. Please be patient and give Github and Composer some time to propagate the changes.&amp;lt;/p&amp;gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/milesj?a=_PxlFv0Zu1Q:Blk4gwLiDck:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/milesj?i=_PxlFv0Zu1Q:Blk4gwLiDck:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/milesj?a=_PxlFv0Zu1Q:Blk4gwLiDck:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/milesj?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/milesj?a=_PxlFv0Zu1Q:Blk4gwLiDck:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/milesj?i=_PxlFv0Zu1Q:Blk4gwLiDck:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/milesj?a=_PxlFv0Zu1Q:Blk4gwLiDck:TzevzKxY174"&gt;&lt;img src="http://feeds.feedburner.com/~ff/milesj?d=TzevzKxY174" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/milesj?a=_PxlFv0Zu1Q:Blk4gwLiDck:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/milesj?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/milesj/~4/_PxlFv0Zu1Q" height="1" width="1"/&gt;</description><author>Miles Johnson</author><pubDate>Wed, 23 Jan 2013 14:34:06 -0800</pubDate><category>Code</category><category>Other</category><category>Programming</category><feedburner:origLink>http://milesj.me/blog/read/repository-cleanup</feedburner:origLink></item><item><title>Decoda v5.1.0</title><link>http://feedproxy.google.com/~r/milesj/~3/xcicgmwvo2k/changelog-decoda-5.1.0</link><guid isPermaLink="false">http://milesj.me/blog/read/changelog-decoda-5.1.0</guid><description>&amp;lt;p&amp;gt;A new version of Decoda has been released, version &amp;lt;b&amp;gt;5.1.0&amp;lt;/b&amp;gt;. Please &amp;lt;a href=&amp;quot;https://github.com/milesj/php-decoda/tags&amp;quot;&amp;gt;download the new tag&amp;lt;/a&amp;gt; or &amp;lt;a href=&amp;quot;http://milesj.me/c/6&amp;quot;&amp;gt;view the documentation&amp;lt;/a&amp;gt;. If you have any questions, be sure to send me an email or comment on this post. If you run into any problems, be sure to report an issue on the Github repository.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;Version:&amp;lt;/b&amp;gt; 5.1.0&amp;lt;br&amp;gt;
&amp;lt;b&amp;gt;Tested On:&amp;lt;/b&amp;gt; PHP 5.4, Composer&amp;lt;br&amp;gt;
&amp;lt;b&amp;gt;Requires:&amp;lt;/b&amp;gt; PHP 5.3, Composer&amp;lt;br&amp;gt;
&amp;lt;b&amp;gt;Commit Hash:&amp;lt;/b&amp;gt; &amp;lt;a href=&amp;quot;https://github.com/milesj/php-decoda/commit/b554ba63750bf2c32b0e22b757fed57d5adb981f&amp;quot;&amp;gt;b554ba63750bf2c32b0e22b757fed57d5adb981f&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;
&amp;lt;b&amp;gt;Changes:&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;ul class=&amp;quot;list&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;Updated to use Multibyte extensively &amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Added Decoda::hasFilter() and Decoda::hasHook()&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Added &amp;amp;lt;code&amp;amp;gt; tags within &amp;amp;lt;pre&amp;amp;gt; for CodeFilter and proper semantics&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Added source tag that renders &amp;amp;lt;code&amp;amp;gt; tag for CodeFilter&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Refactored Decoda::_buildTag() to be more efficient&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Fixed bugs with custom brackets in tag parsing&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Fixed bugs with auto-linking regex&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Fixed bug with URLs that end in trailing slash&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Changed &amp;amp;lt;code&amp;amp;gt; to &amp;amp;lt;var&amp;amp;gt; for var tag&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/milesj?a=xcicgmwvo2k:Y9CNAJjYXjQ:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/milesj?i=xcicgmwvo2k:Y9CNAJjYXjQ:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/milesj?a=xcicgmwvo2k:Y9CNAJjYXjQ:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/milesj?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/milesj?a=xcicgmwvo2k:Y9CNAJjYXjQ:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/milesj?i=xcicgmwvo2k:Y9CNAJjYXjQ:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/milesj?a=xcicgmwvo2k:Y9CNAJjYXjQ:TzevzKxY174"&gt;&lt;img src="http://feeds.feedburner.com/~ff/milesj?d=TzevzKxY174" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/milesj?a=xcicgmwvo2k:Y9CNAJjYXjQ:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/milesj?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/milesj/~4/xcicgmwvo2k" height="1" width="1"/&gt;</description><author>Miles Johnson</author><pubDate>Sun, 20 Jan 2013 00:28:23 -0800</pubDate><category>PHP</category><feedburner:origLink>http://milesj.me/blog/read/changelog-decoda-5.1.0</feedburner:origLink></item><item><title>Uploader v4.0.0</title><link>http://feedproxy.google.com/~r/milesj/~3/bTInoXRswTM/changelog-uploader-4.0.0</link><guid isPermaLink="false">http://milesj.me/blog/read/changelog-uploader-4.0.0</guid><description>&amp;lt;p&amp;gt;A new version of Uploader has been released, version &amp;lt;b&amp;gt;4.0.0&amp;lt;/b&amp;gt;. Please &amp;lt;a href=&amp;quot;https://github.com/milesj/cake-uploader/tags&amp;quot;&amp;gt;download the new tag&amp;lt;/a&amp;gt; or &amp;lt;a href=&amp;quot;http://milesj.me/c/9&amp;quot;&amp;gt;view the documentation&amp;lt;/a&amp;gt;. If you have any questions, be sure to send me an email or comment on this post. If you run into any problems, be sure to report an issue on the Github repository.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;Version:&amp;lt;/b&amp;gt; 4.0.0&amp;lt;br&amp;gt;
&amp;lt;b&amp;gt;Tested On:&amp;lt;/b&amp;gt; PHP 5.4&amp;lt;br&amp;gt;
&amp;lt;b&amp;gt;Requires:&amp;lt;/b&amp;gt; PHP 5.3&amp;lt;br&amp;gt;
&amp;lt;b&amp;gt;Commit Hash:&amp;lt;/b&amp;gt; &amp;lt;a href=&amp;quot;https://github.com/milesj/cake-uploader/commit/f4d115ff504abdb8b1c7e508ae530300ef53409c&amp;quot;&amp;gt;f4d115ff504abdb8b1c7e508ae530300ef53409c&amp;lt;/a&amp;gt;&amp;lt;br&amp;gt;
&amp;lt;b&amp;gt;Changes:&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;ul class=&amp;quot;list&amp;quot;&amp;gt;
&amp;lt;li&amp;gt;Updated to use Composer extensively &amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Updated to use &amp;lt;a href=&amp;quot;https://github.com/milesj/php-transit&amp;quot;&amp;gt;Transit&amp;lt;/a&amp;gt; and &amp;lt;a href=&amp;quot;https://github.com/aws/aws-sdk-php&amp;quot;&amp;gt;AWS SDK&amp;lt;/a&amp;gt; internally&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Uploader and S3 classes have been removed (uploading is done purely in the model layer)&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Transformations can be applied to the original file or used to create new files&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Transformations now support the following options: nameCallback, append, prepend, uploadDir, finalPath, overwrite and self&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Added Model::deleteImages($id) to delete uploaded files and not the record&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Added automatic file deletion when a record is deleted, or a path is being overwritten with a record update&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Added built in support for file uploading and importing (local, remote or stream)&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Added rollback file deletion if the upload process fails&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Added Model::beforeTransport() callback&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Added logging for critical errors&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Added AWS S3 and Glacier transport support&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Added type and mimeType validation rules&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Improved the error handling&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Improved file renaming and moving&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Removed config and mime type mapping&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Removed Test and Vendor files&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Option name was renamed to nameCallback&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Option importFrom was removed as importing is built in&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Option s3 was replaced with transport&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Option metaColumns had keys renamed&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Options baseDir and uploadDir were replaced with tempDir, uploadDir and finalPath&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Options maxNameLength and saveAsFilename were removed&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;a href=&amp;quot;http://milesj.me/code/cakephp/uploader&amp;quot;&amp;gt;View the updated documentation for help&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/milesj?a=bTInoXRswTM:eo196Q_qqO4:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/milesj?i=bTInoXRswTM:eo196Q_qqO4:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/milesj?a=bTInoXRswTM:eo196Q_qqO4:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/milesj?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/milesj?a=bTInoXRswTM:eo196Q_qqO4:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/milesj?i=bTInoXRswTM:eo196Q_qqO4:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/milesj?a=bTInoXRswTM:eo196Q_qqO4:TzevzKxY174"&gt;&lt;img src="http://feeds.feedburner.com/~ff/milesj?d=TzevzKxY174" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/milesj?a=bTInoXRswTM:eo196Q_qqO4:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/milesj?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/milesj/~4/bTInoXRswTM" height="1" width="1"/&gt;</description><author>Miles Johnson</author><pubDate>Wed, 09 Jan 2013 11:04:17 -0800</pubDate><category>CakePHP</category><feedburner:origLink>http://milesj.me/blog/read/changelog-uploader-4.0.0</feedburner:origLink></item></channel></rss>
