text:
Description
===========

Installs and configures PHP 5.3 and the PEAR package management system.  Also includes LWRPs for managing PEAR (and PECL) packages along with PECL channels.

---
Requirements
============

Platform
--------

* Debian, Ubuntu
* CentOS, Red Hat, Fedora

Cookbooks
---------

* build-essential
* xml
* mysql

These cookbooks are only used when building PHP from source.

---
Attributes
==========

* `node["php"]["install_method"]` = method to install php with, default `package`.

The file also contains the following attribute types:

* platform specific locations and settings.
* source installation settings

---
Resource/Provider
=================

This cookbook includes LWRPs for managing:

* PEAR channels
* PEAR/PECL packages

`php_pear_channel`
------------------

[PEAR Channels](http://pear.php.net/manual/en/guide.users.commandline.channels.php) are alternative sources for PEAR packages.  This LWRP provides and easy way to manage these channels.

# Actions

- :discover: Initialize a channel from its server.
- :add: Add a channel to the channel list, usually only used to add private channels.  Public channels are usually added using the `:discover` action
- :update: Update an existing channel
- :remove: Remove a channel from the List

# Attribute Parameters

- channel_name: name attribute. The name of the channel to discover
- channel_xml: the channel.xml file of the channel you are adding

# Example

    # discover the horde channel
    php_pear_channel "pear.horde.org" do
      action :discover
    end

    # download xml then add the symfony channel
    remote_file "#{Chef::Config[:file_cache_path]}/symfony-channel.xml" do
      source "http://pear.symfony-project.com/channel.xml"
      mode 0644
    end
    php_pear_channel "symfony" do
      channel_xml "#{Chef::Config[:file_cache_path]}/symfony-channel.xml"
      action :add
    end

    # update the main pear channel
    php_pear_channel 'pear.php.net' do
      action :update
    end

    # update the main pecl channel
    php_pear_channel 'pecl.php.net' do
      action :update
    end

`php_pear`
----------

[PEAR](http://pear.php.net/) is a framework and distribution system for reusable PHP components. [PECL](http://pecl.php.net/) is a repository for PHP Extensions. PECL contains C extensions for compiling into PHP. As C programs, PECL extensions run more efficiently than PEAR packages. PEARs and PECLs use the same packaging and distribution system.  As such this LWRP is clever enough to abstract away the small differences and can be used for managing either.  This LWRP also creates the proper module .ini file for each PECL extension at the correct location for each supported platform.

# Actions

- :install: Install a pear package - if version is provided, install that specific version
- :upgrade: Upgrade a pear package - if version is provided, upgrade to that specific version
- :remove: Remove a pear package
- :purge: Purge a pear package (this usually entails removing configuration files as well as the package itself).  With pear packages this behaves the same as `:remove`

# Attribute Parameters

- package_name: name attribute. The name of the pear package to install
- version: the version of the pear package to install/upgrade.  If no version is given latest is assumed.
- preferred_state: PEAR by default installs stable packages only, this allows you to install pear packages in a devel, alpha or beta state
- directives: extra extension directives (settings) for a pecl. on most platforms these usually get rendered into the extension's .ini file
- zend_extensions: extension filenames which should be loaded with zend_extension.
- options: Add additional options to the underlying pear package command

# Example

    # upgrade a pear
    php_pear "XML_RPC" do
      action :upgrade
    end

    # install a specific version
    php_pear "XML_RPC" do
      version "1.5.4"
      action :install
    end

    # install the mongodb pecl
    php_pear "mongo" do
      action :install
    end

    # install the xdebug pecl
    php_pear "xdebug" do
      # Specify that xdebug.so must be loaded as a zend extension
      zend_extensions ['xdebug.so']
      action :install
    end

    # install apc pecl with directives
    php_pear "apc" do
      action :install
      directives(:shm_size => 128, :enable_cli => 1)
    end

    # install the beta version of Horde_Url
    # from the horde channel
    hc = php_pear_channel "pear.horde.org" do
      action :discover
    end
    php_pear "Horde_Url" do
      preferred_state "beta"
      channel hc.channel_name
      action :install
    end

    # install the YAML pear from the symfony project
    sc = php_pear_channel "pear.symfony-project.com" do
      action :discover
    end
    php_pear "YAML" do
      channel sc.channel_name
      action :install
    end

---
Recipes
=======

default
-------

Include the default recipe in a run list, to get `php`.  By default `php` is installed from packages but this can be changed by using the `install_method` attribute.

package
-------

This recipe installs PHP from packages.

source
------

This recipe installs PHP from source.

---
Deprecated Recipes
==================

The following recipes are deprecated and will be removed from a future version of this cookbook.

* `module_apc`
* `module_curl`
* `module_fileinfo`
* `module_fpdf`
* `module_gd`
* `module_ldap`
* `module_memcache`
* `module_mysql`
* `module_pgsql`
* `module_sqlite3`

The installation of the php modules in these recipes can now be accomplished by installing from a native package or via the new php_pear LWRP.  For example, the functionality of the `module_memcache` recipe can be enabled in the following ways:

    # using apt
    package "php5-memcache" do
      action :install
    end

    # using pear LWRP
    php_pear "memcache" do
      action :install
    end

---
Usage
=====

Simply include the `php` recipe where ever you would like php installed.  To install from source override the `node['php']['install_method']` attribute with in a role:

    name "php"
    description "Install php from source"
    override_attributes(
      "php" => {
        "install_method" => "source"
      }
    )
    run_list(
      "recipe[php]"
    )

License and Author
==================

Author:: Seth Chisamore (<schisamo@opscode.com>)
Author:: Joshua Timberman (<joshua@opscode.com>)

Copyright:: 2011, Opscode, Inc

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.


text:
#
# Author:: Seth Chisamore <schisamo@opscode.com>
# Cookbook Name:: php
# Resource:: pear_package
#
# Copyright:: 2011, Opscode, Inc <legal@opscode.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

actions :install, :upgrade, :remove, :purge

attribute :package_name, :kind_of => String, :name_attribute => true
attribute :version, :default => nil
attribute :channel, :kind_of => String
attribute :options, :kind_of => String
attribute :directives, :kind_of => Hash, :default => {}
attribute :zend_extensions, :kind_of => Array, :default => Array.new
attribute :preferred_state, :default => 'stable'

repo_name: michael-romer/zf-boilerplate

repo_language: PHP

mime_type: text/html


text:
#
# Author:: Seth Chisamore <schisamo@opscode.com>
# Cookbook Name:: php
# Resource:: pear_channel
#
# Copyright:: 2011, Opscode, Inc <legal@opscode.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

actions :discover, :add, :update, :remove

attribute :channel_name, :kind_of => String, :name_attribute => true
attribute :channel_xml, :kind_of => String

# TODO add authenticated channel support!
# attribute :username, :kind_of => String
# attribute :password, :kind_of => String


text:
#
# Author:: Seth Chisamore <schisamo@opscode.com>
# Cookbook Name:: php
# Provider:: pear_package
#
# Copyright:: 2011, Opscode, Inc <legal@opscode.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

require 'chef/mixin/shell_out'
require 'chef/mixin/language'
include Chef::Mixin::ShellOut

# the logic in all action methods mirror that of
# the Chef::Provider::Package which will make
# refactoring into core chef easy

action :install do
  # If we specified a version, and it's not the current version, move to the specified version
  if @new_resource.version != nil && @new_resource.version != @current_resource.version
    install_version = @new_resource.version
  # If it's not installed at all, install it
  elsif @current_resource.version == nil
    install_version = candidate_version
  end

  if install_version
    Chef::Log.info("Installing #{@new_resource} version #{install_version}")
    status = install_package(@new_resource.package_name, install_version)
    if status
      @new_resource.updated_by_last_action(true)
    end
  end
end

action :upgrade do
  if @current_resource.version != candidate_version
    orig_version = @current_resource.version || "uninstalled"
    Chef::Log.info("Upgrading #{@new_resource} version from #{orig_version} to #{candidate_version}")
    status = upgrade_package(@new_resource.package_name, candidate_version)
    if status
      @new_resource.updated_by_last_action(true)
    end
  end
end

action :remove do
  if removing_package?
    Chef::Log.info("Removing #{@new_resource}")
    remove_package(@current_resource.package_name, @new_resource.version)
    @new_resource.updated_by_last_action(true)
  else
  end
end

action :purge do
  if removing_package?
    Chef::Log.info("Purging #{@new_resource}")
    purge_package(@current_resource.package_name, @new_resource.version)
    @new_resource.updated_by_last_action(true)
  end
end

def removing_package?
  if @current_resource.version.nil?
    false # nothing to remove
  elsif @new_resource.version.nil?
    true # remove any version of a package
  elsif @new_resource.version == @current_resource.version
    true # remove the version we have
  else
    false # we don't have the version we want to remove
  end
end

def expand_options(options)
  options ? " #{options}" : ""
end

# these methods are the required overrides of
# a provider that extends from Chef::Provider::Package
# so refactoring into core Chef should be easy

def load_current_resource
  @current_resource = Chef::Resource::PhpPear.new(@new_resource.name)
  @current_resource.package_name(@new_resource.package_name)
  @bin = 'pear'
  if pecl?
    Chef::Log.debug("#{@new_resource} smells like a pecl...installing package in Pecl mode.")
    @bin = 'pecl'
  end
  Chef::Log.debug("#{@current_resource}: Installed version: #{current_installed_version} Candidate version: #{candidate_version}")

  unless current_installed_version.nil?
    @current_resource.version(current_installed_version)
    Chef::Log.debug("Current version is #{@current_resource.version}") if @current_resource.version
  end
  @current_resource
end

def current_installed_version
  @current_installed_version ||= begin
    v = nil
    version_check_cmd = "#{@bin} -d preferred_state=#{can_haz(@new_resource, "preferred_state")} list#{expand_channel(can_haz(@new_resource, "channel"))}"
    p = shell_out(version_check_cmd)
    response = nil
    if p.stdout =~ /\.?Installed packages/i
      response = grep_for_version(p.stdout, @new_resource.package_name)
    end
    response
  end
end

def candidate_version
  @candidate_version ||= begin
    candidate_version_cmd = "#{@bin} -d preferred_state=#{can_haz(@new_resource, "preferred_state")} search#{expand_channel(can_haz(@new_resource, "channel"))} #{@new_resource.package_name}"
    p = shell_out(candidate_version_cmd)
    response = nil
    if p.stdout =~ /\.?Matched packages/i
      response = grep_for_version(p.stdout, @new_resource.package_name)
    end
    response
  end
end

def install_package(name, version)
  pear_shell_out("echo -e \"\\r\" | #{@bin} -d preferred_state=#{can_haz(@new_resource, "preferred_state")} install -a#{expand_options(@new_resource.options)} #{prefix_channel(can_haz(@new_resource, "channel"))}#{name}-#{version}")
  manage_pecl_ini(name, :create, can_haz(@new_resource, "directives"), can_haz(@new_resource, "zend_extensions")) if pecl?
end

def upgrade_package(name, version)
  pear_shell_out("echo -e \"\\r\" | #{@bin} -d preferred_state=#{can_haz(@new_resource, "preferred_state")} upgrade -a#{expand_options(@new_resource.options)} #{prefix_channel(can_haz(@new_resource, "channel"))}#{name}-#{version}")
  manage_pecl_ini(name, :create, can_haz(@new_resource, "directives"), can_haz(@new_resource, "zend_extensions")) if pecl?
end

def remove_package(name, version)
  command = "#{@bin} uninstall #{expand_options(@new_resource.options)} #{prefix_channel(can_haz(@new_resource, "channel"))}#{name}"
  command << "-#{version}" if version and !version.empty?
  pear_shell_out(command)
  manage_pecl_ini(name, :delete) if pecl?
end

def pear_shell_out(command)
  p = shell_out!(command)
  # pear/pecl commands return a 0 on failures...we'll grep for it
  if p.stdout.split("\n").last =~ /^ERROR:.+/i
    p.invalid!
  end
  p
end

def purge_package(name, version)
  remove_package(name, version)
end

def expand_channel(channel)
  channel ? " -c #{channel}" : ""
end

def prefix_channel(channel)
  channel ? "#{channel}/" : ""
end

def get_extension_dir()
  @extension_dir ||= begin
    p = shell_out("php-config --extension-dir")
    p.stdout.strip
  end
end

def get_extension_files(name)
  files = []

  p = shell_out("#{@bin} list-files #{name}")
  p.stdout.each_line.grep(/^src\s+.*\.so$/i).each do |line|
    files << line.split[1]
  end

  files
end

def manage_pecl_ini(name, action, directives, zend_extensions)
  ext_prefix = get_extension_dir()
  ext_prefix << ::File::SEPARATOR if ext_prefix[-1].chr != ::File::SEPARATOR

  files = get_extension_files(name)

  extensions = Hash[ files.map { |filepath|
    rel_file = filepath.clone
    rel_file.slice! ext_prefix if rel_file.start_with? ext_prefix

    zend = zend_extensions.include?(rel_file)

    [ (zend ? filepath : rel_file) , zend ]
  }]

  template "#{node['php']['ext_conf_dir']}/#{name}.ini" do
    source "extension.ini.erb"
    cookbook "php"
    owner "root"
    group "root"
    mode "0644"
    variables(:name => name, :extensions => extensions, :directives => directives)
    action action
  end
end

def grep_for_version(stdout, package)
  v = nil

  stdout.split(/\n/).grep(/^#{package}\s/i).each do |m|
    # XML_RPC          1.5.4    stable
    # mongo   1.1.4/(1.1.4 stable) 1.1.4 MongoDB database driver
    # Horde_Url -n/a-/(1.0.0beta1 beta)       Horde Url class
    # Horde_Url 1.0.0beta1 (beta) 1.0.0beta1 Horde Url class
    v = m.split(/\s+/)[1].strip
    if v.split(/\//)[0] =~ /.\./
      # 1.1.4/(1.1.4 stable)
      v = v.split(/\//)[0]
    else
      # -n/a-/(1.0.0beta1 beta)
      v = v.split(/(.*)\/\((.*)/).last.split(/\s/)[0]
    end
  end
  v
end

def pecl?
  @pecl ||= begin
    # search as a pear first since most 3rd party channels will report pears as pecls!
    search_cmd = "pear -d preferred_state=#{can_haz(@new_resource, "preferred_state")} search#{expand_channel(can_haz(@new_resource, "channel"))} #{@new_resource.package_name}"
    if shell_out(search_cmd).stdout =~ /\.?Matched packages/i
      false
    else
      # fall back and search as a pecl
      search_cmd = "pecl -d preferred_state=#{can_haz(@new_resource, "preferred_state")} search#{expand_channel(can_haz(@new_resource, "channel"))} #{@new_resource.package_name}"
      if shell_out(search_cmd).stdout =~ /\.?Matched packages/i
        true
      else
        false
      end
    end
  end
end

# TODO remove when provider is moved into Chef core
# this allows PhpPear to work with Chef::Resource::Package
def can_haz(resource, attribute_name)
  resource.respond_to?(attribute_name) ? resource.send(attribute_name) : nil
end


text:
#
# Author:: Seth Chisamore <schisamo@opscode.com>
# Cookbook Name:: php
# Provider:: pear_channel
#
# Copyright:: 2011, Opscode, Inc <legal@opscode.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

# http://pear.php.net/manual/en/guide.users.commandline.channels.php

require 'chef/mixin/shell_out'
require 'chef/mixin/language'
include Chef::Mixin::ShellOut

action :discover do
  unless exists?
    Chef::Log.info("Discovering pear channel #{@new_resource}")
    execute "pear channel-discover #{@new_resource.channel_name}" do
      action :run
    end
    new_resource.updated_by_last_action(true)
  end
end

action :add do
  unless exists?
    Chef::Log.info("Adding pear channel #{@new_resource} from #{@new_resource.channel_xml}")
    execute "pear channel-add #{@new_resource.channel_xml}" do
      action :run
    end
    new_resource.updated_by_last_action(true)
  end
end

action :update do
  if exists?
    update_needed = false
    begin
      updated_needed = true if shell_out("pear search -c #{@new_resource.channel_name} NNNNNN").stdout =~ /channel-update/
    rescue Chef::Exceptions::CommandTimeout
      # CentOS can hang on 'pear search' if a channel needs updating
      Chef::Log.info("Timed out checking if channel-update needed...forcing update of pear channel #{@new_resource}")
      update_needed = true
    end
    if update_needed
      Chef::Log.info("Updating pear channel #{@new_resource}")
      shell_out!("pear channel-update #{@new_resource.channel_name}")
      new_resource.updated_by_last_action(true)
    end
  end
end

action :remove do
  if exists?
    Chef::Log.info("Deleting pear channel #{@new_resource}")
    execute "pear channel-delete #{@new_resource.channel_name}" do
      action :run
    end
    new_resource.updated_by_last_action(true)
  end
end

def load_current_resource
  @current_resource = Chef::Resource::PhpPearChannel.new(@new_resource.name)
  @current_resource.channel_name(@new_resource.channel_name)
  @current_resource
end

private
def exists?
  begin
    shell_out!("pear channel-info #{@current_resource.channel_name}")
    true
  rescue Chef::Exceptions::ShellCommandFailed
    false
  rescue Mixlib::ShellOut::ShellCommandFailed
    false
  end
end


text:
#
# Author::  Joshua Timberman (<joshua@opscode.com>)
# Author::  Seth Chisamore (<schisamo@opscode.com>)
# Cookbook Name:: php
# Recipe:: module_mysql
#
# Copyright 2009-2011, Opscode, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

pkg = value_for_platform(
  %w(centos redhat scientific fedora) => {
    %w(5.0 5.1 5.2 5.3 5.4 5.5 5.6 5.7 5.8) => "php53-mysql",
    "default" => "php-mysql"
  },
  "default" => "php5-mysql"
)

package pkg do
  action :install
end


text:
#
# Author::  Joshua Timberman (<joshua@opscode.com>)
# Author::  Seth Chisamore (<schisamo@opscode.com>)
# Cookbook Name:: php
# Recipe:: module_apc
#
# Copyright 2009-2011, Opscode, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

case node['platform']
when "centos", "redhat", "fedora", "scientific"
  %w{ httpd-devel pcre pcre-devel }.each do |pkg|
    package pkg do
      action :install
    end
  end
  php_pear "apc" do
    action :install
    directives(:shm_size => "128M", :enable_cli => 0)
  end
when "debian", "ubuntu"
  package "php-apc" do
    action :install
  end
end


text:
#
# Author::  Joshua Timberman (<joshua@opscode.com>)
# Author::  Seth Chisamore (<schisamo@opscode.com>)
# Cookbook Name:: php
# Recipe:: module_fpdf
#
# Copyright 2009-2011, Opscode, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

case node['platform']
when "centos", "redhat", "fedora", "scientific"
  pearhub_chan = php_pear_channel "pearhub.org" do
    action :discover
  end
  php_pear "FPDF" do
    channel pearhub_chan.channel_name
    action :install
  end
when "debian", "ubuntu"
  package "php-fpdf" do
    action :install
  end
end


text:
#
# Author::  Joshua Timberman (<joshua@opscode.com>)
# Author::  Seth Chisamore (<schisamo@opscode.com>)
# Cookbook Name:: php
# Recipe:: module_memcache
#
# Copyright 2009-2011, Opscode, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

case node['platform']
when "centos", "redhat", "fedora", "scientific"
  %w{ zlib-devel }.each do |pkg|
    package pkg do
      action :install
    end
  end
  php_pear "memcache" do
    action :install
    #directives(:shm_size => "128M", :enable_cli => 0)
  end
when "debian", "ubuntu"
  package "php5-memcache" do
    action :install
  end
end


text:
#
# Author::  Seth Chisamore (<schisamo@opscode.com>)
# Cookbook Name:: php
# Recipe:: package
#
# Copyright 2011, Opscode, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

pkgs = value_for_platform(
  %w(centos redhat scientific fedora) => {
    %w(5.0 5.1 5.2 5.3 5.4 5.5 5.6 5.7 5.8) => %w(php53 php53-devel php53-cli php-pear),
    'default' => %w(php php-devel php-cli php-pear)
  },
  [ "debian", "ubuntu" ] => {
    "default" => %w{ php5-cgi php5 php5-dev php5-cli php-pear }
  },
  "default" => %w{ php5-cgi php5 php5-dev php5-cli php-pear }
)

pkgs.each do |pkg|
  package pkg do
    action :install
  end
end

template "#{node['php']['conf_dir']}/php.ini" do
  source "php.ini.erb"
  owner "root"
  group "root"
  mode "0644"
end


text:
#
# Author::  Joshua Timberman (<joshua@opscode.com>)
# Author::  Seth Chisamore (<schisamo@opscode.com>)
# Cookbook Name:: php
# Recipe:: module_sqlite3
#
# Copyright 2009-2011, Opscode, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

case node['platform']
when "centos", "redhat", "fedora", "scientific"
  #already there in centos, --with-pdo-sqlite=shared
when "debian", "ubuntu"
  package "php5-sqlite" do
    action :install
  end
end


text:
#
# Author::  Joshua Timberman (<joshua@opscode.com>)
# Author::  Seth Chisamore (<schisamo@opscode.com>)
# Cookbook Name:: php
# Recipe:: module_curl
#
# Copyright 2009-2011, Opscode, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

case node['platform']
when "centos", "redhat", "fedora", "scientific"
  # centos php compiled with curl
when "debian", "ubuntu"
  package "php5-curl" do
    action :upgrade
  end
end


text:
#
# Author::  Joshua Timberman (<joshua@opscode.com>)
# Author::  Seth Chisamore (<schisamo@opscode.com>)
# Cookbook Name:: php
# Recipe:: module_gd
#
# Copyright 2009-2011, Opscode, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

pkg = value_for_platform(
  %w(centos redhat scientific fedora) => {
    %w(5.0 5.1 5.2 5.3 5.4 5.5 5.6 5.7 5.8) => "php53-gd",
    "default" => "php-gd"
  },
  "default" => "php5-gd"
)

package pkg do
  action :install
end


text:
#
# Author::  Dustin Currie (<dustin@onlinedesert.com>)
# Cookbook Name:: php
# Recipe:: module_xdebug
#
# Copyright 2010, Dustin Currie
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

pack = value_for_platform(
  [ "centos", "redhat", "fedora", "suse" ] => {
    "default" => "php-xdebug"
  },
  "default" => "php5-xdebug"
)

# need to dynamically add config b/c of php 5.3 xdebug incompatibility
# http://www.eclipse.org/forums/index.php?t=msg&goto=538019&
template value_for_platform([ "centos", "redhat", "fedora", "suse" ] => {"default" => "/etc/xdebug.ini"}, "default" => "/etc/php5/apache2/conf.d/xdebug.ini") do
  source "xdebug.ini.erb"
  owner "root"
  group "root"
  mode 0644
  notifies :restart, resources("service[apache2]"), :delayed
end

package pack do
  action :upgrade
end


text:
#
# Author::  Joshua Timberman (<joshua@opscode.com>)
# Author::  Seth Chisamore (<schisamo@opscode.com>)
# Cookbook Name:: php
# Recipe:: module_fileinfo
#
# Copyright 2009-2011, Opscode, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

case node['platform']
when "centos", "redhat", "fedora", "scientific"
  # enabled by default in php53
when "debian", "ubuntu"
  package "php5-fileinfo" do
    action :upgrade
  end
end


text:
#
# Author::  Joshua Timberman (<joshua@opscode.com>)
# Author::  Seth Chisamore (<schisamo@opscode.com>)
# Cookbook Name:: php
# Recipe:: module_pgsql
#
# Copyright 2009-2011, Opscode, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

pkg = value_for_platform(
  %w(centos redhat scientific fedora) => {
    %w(5.0 5.1 5.2 5.3 5.4 5.5 5.6 5.7 5.8) => "php53-pgsql",
    "default" => "php-pgsql"
  },
  "default" => "php5-pgsql"
)

package pkg do
  action :install
end


text:
#
# Author::  Joshua Timberman (<joshua@opscode.com>)
# Author::  Seth Chisamore (<schisamo@opscode.com>)
# Cookbook Name:: php
# Recipe:: default
#
# Copyright 2009-2011, Opscode, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

include_recipe "php::#{node['php']['install_method']}"

# update the main channels
php_pear_channel 'pear.php.net' do
  action :update
end

php_pear_channel 'pecl.php.net' do
  action :update
end


text:
#
# Author::  Joshua Timberman (<joshua@opscode.com>)
# Author::  Seth Chisamore (<schisamo@opscode.com>)
# Cookbook Name:: php
# Recipe:: module_ldap
#
# Copyright 2009-2011, Opscode, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

pkg = value_for_platform(
  %w(centos redhat scientific fedora) => {
    %w(5.0 5.1 5.2 5.3 5.4 5.5 5.6 5.7 5.8) => "php53-ldap",
    "default" => "php-ldap"
  },
  "default" => "php5-ldap"
)

package pkg do
  action :install
end


text:
#
# Author::  Seth Chisamore (<schisamo@opscode.com>)
# Cookbook Name:: php
# Recipe:: package
#
# Copyright 2011, Opscode, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

configure_options = node['php']['configure_options'].join(" ")

include_recipe "build-essential"
include_recipe "xml"
include_recipe "mysql::client" if configure_options =~ /mysql/

pkgs = value_for_platform(
    ["centos","redhat","fedora", "scientific"] =>
        {"default" => %w{ bzip2-devel libc-client-devel curl-devel freetype-devel gmp-devel libjpeg-devel krb5-devel libmcrypt-devel libpng-devel openssl-devel t1lib-devel mhash-devel }},
    [ "debian", "ubuntu" ] =>
        {"default" => %w{ libbz2-dev libc-client2007e-dev libcurl4-gnutls-dev libfreetype6-dev libgmp3-dev libjpeg62-dev libkrb5-dev libmcrypt-dev libpng12-dev libssl-dev libt1-dev }},
    "default" => %w{ libbz2-dev libc-client2007e-dev libcurl4-gnutls-dev libfreetype6-dev libgmp3-dev libjpeg62-dev libkrb5-dev libmcrypt-dev libpng12-dev libssl-dev libt1-dev }
  )

pkgs.each do |pkg|
  package pkg do
    action :install
  end
end

version = node['php']['version']

remote_file "#{Chef::Config[:file_cache_path]}/php-#{version}.tar.gz" do
  source "#{node['php']['url']}/php-#{version}.tar.gz"
  checksum node['php']['checksum']
  mode "0644"
  not_if "which php"
end

bash "build php" do
  cwd Chef::Config[:file_cache_path]
  code <<-EOF
  tar -zxvf php-#{version}.tar.gz
  (cd php-#{version} && ./configure #{configure_options})
  (cd php-#{version} && make && make install)
  EOF
  not_if "which php"
end

directory node['php']['conf_dir'] do
  owner "root"
  group "root"
  mode "0755"
  recursive true
end

directory node['php']['ext_conf_dir'] do
  owner "root"
  group "root"
  mode "0755"
  recursive true
end

template "#{node['php']['conf_dir']}/php.ini" do
  source "php.ini.erb"
  owner "root"
  group "root"
  mode "0644"
end


text:
#
# Author:: Seth Chisamore (<schisamo@opscode.com>)
# Cookbook Name:: php
# Attribute:: default
#
# Copyright 2011, Opscode, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

lib_dir = kernel['machine'] =~ /x86_64/ ? 'lib64' : 'lib'

default['php']['install_method'] = 'package'

case node["platform"]
when "centos", "redhat", "fedora"
  default['php']['conf_dir']      = '/etc'
  default['php']['ext_conf_dir']  = '/etc/php.d'
  default['php']['fpm_user']      = 'nobody'
  default['php']['fpm_group']     = 'nobody'
  default['php']['ext_dir']       = "/usr/#{lib_dir}/php/modules"
when "debian", "ubuntu"
  default['php']['conf_dir']      = '/etc/php5/cli'
  default['php']['ext_conf_dir']  = '/etc/php5/conf.d'
  default['php']['fpm_user']      = 'www-data'
  default['php']['fpm_group']     = 'www-data'
else
  default['php']['conf_dir']      = '/etc/php5/cli'
  default['php']['ext_conf_dir']  = '/etc/php5/conf.d'
  default['php']['fpm_user']      = 'www-data'
  default['php']['fpm_group']     = 'www-data'
end

default['php']['url'] = 'http://us.php.net/distributions'
default['php']['version'] = '5.3.10'
default['php']['checksum'] = 'ee26ff003eaeaefb649735980d9ef1ffad3ea8c2836e6ad520de598da225eaab'
default['php']['prefix_dir'] = '/usr/local'

default['php']['configure_options'] = %W{--prefix=#{php['prefix_dir']}
                                          --with-libdir=#{lib_dir}
                                          --with-config-file-path=#{php['conf_dir']}
                                          --with-config-file-scan-dir=#{php['ext_conf_dir']}
                                          --with-pear
                                          --enable-fpm
                                          --with-fpm-user=#{php['fpm_user']}
                                          --with-fpm-group=#{php['fpm_group']}
                                          --with-zlib
                                          --with-openssl
                                          --with-kerberos
                                          --with-bz2
                                          --with-curl
                                          --enable-ftp
                                          --enable-zip
                                          --enable-exif
                                          --with-gd
                                          --enable-gd-native-ttf
                                          --with-gettext
                                          --with-gmp
                                          --with-mhash
                                          --with-iconv
                                          --with-imap
                                          --with-imap-ssl
                                          --enable-sockets
                                          --enable-soap
                                          --with-xmlrpc
                                          --with-libevent-dir
                                          --with-mcrypt
                                          --enable-mbstring
                                          --with-t1lib
                                          --with-mysql
                                          --with-mysqli=/usr/bin/mysql_config
                                          --with-mysql-sock
                                          --with-sqlite3
                                          --with-pdo-mysql
                                          --with-pdo-sqlite}


text:
[PHP]

;;;;;;;;;;;;;;;;;;;
; About php.ini   ;
;;;;;;;;;;;;;;;;;;;
; This file controls many aspects of PHP's behavior.  In order for PHP to
; read it, it must be named 'php.ini'.  PHP looks for it in the current
; working directory, in the path designated by the environment variable
; PHPRC, and in the path that was defined in compile time (in that order).
; Under Windows, the compile-time path is the Windows directory.  The
; path in which the php.ini file is looked for can be overridden using
; the -c argument in command line mode.
;
; The syntax of the file is extremely simple.  Whitespace and Lines
; beginning with a semicolon are silently ignored (as you probably guessed).
; Section headers (e.g. [Foo]) are also silently ignored, even though
; they might mean something in the future.
;
; Directives are specified using the following syntax:
; directive = value
; Directive names are *case sensitive* - foo=bar is different from FOO=bar.
;
; The value can be a string, a number, a PHP constant (e.g. E_ALL or M_PI), one
; of the INI constants (On, Off, True, False, Yes, No and None) or an expression
; (e.g. E_ALL & ~E_NOTICE), or a quoted string ("foo").
;
; Expressions in the INI file are limited to bitwise operators and parentheses:
; |        bitwise OR
; &        bitwise AND
; ~        bitwise NOT
; !        boolean NOT
;
; Boolean flags can be turned on using the values 1, On, True or Yes.
; They can be turned off using the values 0, Off, False or No.
;
; An empty string can be denoted by simply not writing anything after the equal
; sign, or by using the None keyword:
;
;  foo =         ; sets foo to an empty string
;  foo = none    ; sets foo to an empty string
;  foo = "none"  ; sets foo to the string 'none'
;
; If you use constants in your value, and these constants belong to a
; dynamically loaded extension (either a PHP extension or a Zend extension),
; you may only use these constants *after* the line that loads the extension.
;
;
;;;;;;;;;;;;;;;;;;;
; About this file ;
;;;;;;;;;;;;;;;;;;;
; This is the recommended, PHP 5-style version of the php.ini-dist file.  It
; sets some non standard settings, that make PHP more efficient, more secure,
; and encourage cleaner coding.
;
; The price is that with these settings, PHP may be incompatible with some
; applications, and sometimes, more difficult to develop with.  Using this
; file is warmly recommended for production sites.  As all of the changes from
; the standard settings are thoroughly documented, you can go over each one,
; and decide whether you want to use it or not.
;
; For general information about the php.ini file, please consult the php.ini-dist
; file, included in your PHP distribution.
;
; This file is different from the php.ini-dist file in the fact that it features
; different values for several directives, in order to improve performance, while
; possibly breaking compatibility with the standard out-of-the-box behavior of
; PHP.  Please make sure you read what's different, and modify your scripts
; accordingly, if you decide to use this file instead.
;
; - register_globals = Off         [Security, Performance]
;     Global variables are no longer registered for input data (POST, GET, cookies,
;     environment and other server variables).  Instead of using $foo, you must use
;     you can use $_REQUEST["foo"] (includes any variable that arrives through the
;     request, namely, POST, GET and cookie variables), or use one of the specific
;     $_GET["foo"], $_POST["foo"], $_COOKIE["foo"] or $_FILES["foo"], depending
;     on where the input originates.  Also, you can look at the
;     import_request_variables() function.
;     Note that register_globals is going to be depracated (i.e., turned off by
;     default) in the next version of PHP, because it often leads to security bugs.
;     Read http://php.net/manual/en/security.registerglobals.php for further
;     information.
; - register_long_arrays = Off     [Performance]
;     Disables registration of the older (and deprecated) long predefined array
;     variables ($HTTP_*_VARS).  Instead, use the superglobals that were
;     introduced in PHP 4.1.0
; - display_errors = Off           [Security]
;     With this directive set to off, errors that occur during the execution of
;     scripts will no longer be displayed as a part of the script output, and thus,
;     will no longer be exposed to remote users.  With some errors, the error message
;     content may expose information about your script, web server, or database
;     server that may be exploitable for hacking.  Production sites should have this
;     directive set to off.
; - log_errors = On                [Security]
;     This directive complements the above one.  Any errors that occur during the
;     execution of your script will be logged (typically, to your server's error log,
;     but can be configured in several ways).  Along with setting display_errors to off,
;     this setup gives you the ability to fully understand what may have gone wrong,
;     without exposing any sensitive information to remote users.
; - output_buffering = 4096        [Performance]
;     Set a 4KB output buffer.  Enabling output buffering typically results in less
;     writes, and sometimes less packets sent on the wire, which can often lead to
;     better performance.  The gain this directive actually yields greatly depends
;     on which Web server you're working with, and what kind of scripts you're using.
; - register_argc_argv = Off       [Performance]
;     Disables registration of the somewhat redundant $argv and $argc global
;     variables.
; - magic_quotes_gpc = Off         [Performance]
;     Input data is no longer escaped with slashes so that it can be sent into
;     SQL databases without further manipulation.  Instead, you should use the
;     function addslashes() on each input element you wish to send to a database.
; - variables_order = "GPCS"       [Performance]
;     The environment variables are not hashed into the $_ENV.  To access
;     environment variables, you can use getenv() instead.
; - error_reporting = E_ALL        [Code Cleanliness, Security(?)]
;     By default, PHP surpresses errors of type E_NOTICE.  These error messages
;     are emitted for non-critical errors, but that could be a symptom of a bigger
;     problem.  Most notably, this will cause error messages about the use
;     of uninitialized variables to be displayed.
; - allow_call_time_pass_reference = Off     [Code cleanliness]
;     It's not possible to decide to force a variable to be passed by reference
;     when calling a function.  The PHP 4 style to do this is by making the
;     function require the relevant argument by reference.

;;;;;;;;;;;;;;;;;;;;
; Language Options ;
;;;;;;;;;;;;;;;;;;;;

; Enable the PHP scripting language engine under Apache.
engine = On

; Enable compatibility mode with Zend Engine 1 (PHP 4.x)
zend.ze1_compatibility_mode = Off

; Allow the <? tag.  Otherwise, only <?php and