<?php

/*
 +--------------------------------------------------------------------+
 | CiviCRM version 3.0                                               |
 +--------------------------------------------------------------------+
 | Copyright CiviCRM LLC (c) 2004-2009                                |
 +--------------------------------------------------------------------+
 | This file is a part of CiviCRM.                                    |
 |                                                                    |
 | CiviCRM is free software; you can copy, modify, and distribute it  |
 | under the terms of the GNU Affero General Public License           |
 | Version 3, 19 November 2007.                                       |
 |                                                                    |
 | CiviCRM is distributed in the hope that it will be useful, but     |
 | WITHOUT ANY WARRANTY; without even the implied warranty of         |
 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.               |
 | See the GNU Affero General Public License for more details.        |
 |                                                                    |
 | You should have received a copy of the GNU Affero General Public   |
 | License along with this program; if not, contact CiviCRM LLC       |
 | at info[AT]civicrm[DOT]org. If you have questions about the        |
 | GNU Affero General Public License or the licensing of CiviCRM,     |
 | see the CiviCRM license FAQ at http://civicrm.org/licensing        |
 +--------------------------------------------------------------------+
*/

/*
 * This file checks and updates the status of all membership records for a given domain using the calc_membership_status and 
 * update_contact_membership APIs.
 * It takes the first argument as the domain-id if specified, otherwise takes the domain-id as 1.
 *
 * IMPORTANT: You must set a valid FROM email address on line 199 before and then save the file as
 * UpdateMembershipRecord.php prior to running this script.
 */

class CRM_UpdateMembershipRecord {
    
    function __construct() 
    {
        $this->initialize( );

        $config =& CRM_Core_Config::singleton();

        // this does not return on failure
        CRM_Utils_System::authenticateScript( true );
    }

    function initialize( ) {
        require_once '../civicrm.config.php';
        require_once 'CRM/Core/Config.php';

        $config =& CRM_Core_Config::singleton();

        require_once 'CRM/Member/BAO/MembershipLog.php';
        require_once 'CRM/Member/BAO/Membership.php';
        require_once 'CRM/Core/BAO/MessageTemplates.php';
        require_once 'CRM/Member/BAO/MembershipType.php';
        require_once 'CRM/Utils/Date.php';
        require_once 'CRM/Utils/System.php';
        require_once 'api/v2/Membership.php';
        require_once 'CRM/Member/PseudoConstant.php';
        require_once 'CRM/Contact/BAO/Contact.php';
        require_once 'CRM/Activity/BAO/Activity.php';
    }
    
    public function updateMembershipStatus( )
    {
	$config =& CRM_Core_Config::singleton();	
        //get all active statuses of membership, CRM-3984
        $allStatus = CRM_Member_PseudoConstant::membershipStatus( );
        $allTypes  = CRM_Member_PseudoConstant::membershipType( );
        
        $query = "
SELECT civicrm_membership.id                 as membership_id,
       civicrm_membership.is_override        as is_override,
       civicrm_membership.reminder_date      as reminder_date,
       civicrm_membership.membership_type_id as membership_type_id,
       civicrm_membership.status_id          as status_id,
       civicrm_membership.join_date          as join_date,
       civicrm_membership.start_date         as start_date,
       civicrm_membership.end_date           as end_date,
       civicrm_membership.source             as source,
       civicrm_contact.id                    as contact_id,
       civicrm_contact.is_deceased           as is_deceased
FROM   civicrm_membership, civicrm_contact
WHERE  civicrm_membership.contact_id = civicrm_contact.id
AND    civicrm_membership.is_test = 0
";
        $params = array( );
        $dao =& CRM_Core_DAO::executeQuery( $query, $params );
        
        $today = date( "Y-m-d" );
        $count = 0;
        while ( $dao->fetch( ) ) {
            echo ".";
            
            /**
            $count++;
            echo $dao->contact_id . ', '. CRM_Utils_System::memory( ) . "<p>\n";

            CRM_Core_Error::debug( 'fBegin', count( $GLOBALS['_DB_DATAOBJECT']['RESULTS'] ) );
            if ( $count > 2 ) {
                foreach ( $GLOBALS['_DB_DATAOBJECT']['RESULTS'] as $r ) {
                    CRM_Core_Error::debug( 'r', $r->query );
                }
                // CRM_Core_Error::debug( 'f', $GLOBALS['_DB_DATAOBJECT']['RESULTS'] );
                exit( );
            }
            **/
            
            //need to handle related memberships records.
            //we have deleted during parent membership processing.
            if ( !CRM_Core_DAO::getFieldValue( 'CRM_Member_DAO_Membership', $dao->membership_id, 'contact_id' ) ) {
                continue;
            }
            
            //update membership record to Deceased if contact is deceased
            if ( $dao->is_deceased ) { 
                //since we are calculating status here so no
                //need to calculate again in BAO::create( );
                $deceasedMembership = array( 'id'                 => $dao->membership_id,
                                             'status_id'          => array_search( 'Deceased', $allStatus ),
                                             'contact_id'         => $dao->contact_id,
                                             'membership_type_id' => $dao->membership_type_id,
                                             'join_date'          => $dao->join_date,
                                             'start_date'         => $dao->start_date,
                                             'end_date'           => $dao->end_date,
                                             'reminder_date'      => $dao->reminder_date,
                                             'source'             => $dao->source,
                                             'skipStatusCal'      => true );
                
                //create activity when status changed. CRM-2521.
                //as BAO::create( ) create activity so let BAO handle it.
                if ( $dao->status_id !=  array_search( 'Deceased', $allStatus ) ) {
                    $deceasedMembership['createActivity'] = true; 
                }
                
                civicrm_contact_membership_create( $deceasedMembership );
                continue;
            }
            
            //update membership records where status is NOT - Pending OR Cancelled.
            //as well as membership is not override.
            //skipping Expired membership records -> reduced extra processing( kiran ) 
            if ( !$dao->is_override &&
                 !in_array( $dao->status_id, array( array_search( 'Pending', $allStatus ),
                                                    array_search( 'Cancelled', $allStatus ),
                                                    array_search( 'Expired', $allStatus ) ) ) ) {
                
                //get the membership status as per id.
                $newStatus = civicrm_membership_status_calc( array( 'membership_id' => $dao->membership_id ) );
                
                if ( CRM_Utils_Array::value( 'id', $newStatus ) ) {
                    
                    //take all params that need to save for
                    //related memberships records. since BAO::create( )
                    //will delete existing and create new records. 
                    //also we are calculating status here, so no
                    //need to calculate again in BAO::create( )
                    $memParams = array( 'id'                 => $dao->membership_id,
                                        'status_id'          => $newStatus['id'],
                                        'contact_id'         => $dao->contact_id,
                                        'membership_type_id' => $dao->membership_type_id,
                                        'join_date'          => $dao->join_date,
                                        'start_date'         => $dao->start_date,
                                        'end_date'           => $dao->end_date,
                                        'reminder_date'      => $dao->reminder_date,
                                        'source'             => $dao->source,
                                        'skipStatusCal'      => true );
                    
                    //create activity when status changed. CRM-2521.
                    //as BAO::create create activity so let BAO handle it.
                    if ( $newStatus['id'] != $dao->status_id ) {
                        $memParams['createActivity'] = true; 
                    }
                    civicrm_contact_membership_create( $memParams );
                }
            }
            
            //convert date from string format to timestamp format
            $reminder_date = CRM_Utils_DATE::unixTime( $dao->reminder_date );
            $today_date    = CRM_Utils_DATE::unixTime( $today );
            
            //send reminder for membership renewal
            if ( $dao->reminder_date &&
                 $dao->reminder_date != '0000-00-00' &&
                 ( $reminder_date <= $today_date ) ) {
                $memType =& new CRM_Member_BAO_MembershipType( );
                
                $memType->id = $dao->membership_type_id;
                if ( $memType->find( true ) &&
                     $memType->renewal_msg_id ) {
                    $toEmail  = CRM_Contact_BAO_Contact::getPrimaryEmail( $dao->contact_id );
                    
                    if ( $toEmail ) {
                        // Set the FROM email address for reminder emails here.
                        // This must be a valid account for your SMTP service.
                        $from = "EMAIL@FIXME.ORG";
                        $result = CRM_Core_BAO_MessageTemplates::sendReminder( $dao->contact_id,
                                                                               $toEmail,
                                                                               $memType->renewal_msg_id,
                                                                               $from );
                        if ( ! $result ||
                             is_a( $result, 'PEAR_Error' ) ) {
                            // we could not send an email, for now we ignore
                            // CRM-3406
                            // at some point we might decide to do something
                        }
                        
                        //set membership reminder date to NULL since we've sent the reminder.
                        CRM_Core_DAO::setFieldValue( 'CRM_Member_DAO_Membership', $dao->membership_id, 'reminder_date', 'null');
                        
                        // insert the activity log record.
                        $activityParams = array( );
                        $activityParams['subject']            = $allTypes[$dao->membership_type_id] . 
                            ": Status - " . $allStatus[$newStatus['id']] . 
                            ", End Date - " . CRM_Utils_Date::customFormat(CRM_Utils_Date::isoToMysql($dao->end_date), $config->dateformatFull);
                        $activityParams['source_record_id']   = $dao->membership_id; 
                        $activityParams['source_contact_id']  = $dao->contact_id; 
                        $activityParams['activity_date_time'] = date('YmdHis');

                        static $actRelIds = array( );
                        if ( ! isset($actRelIds['activity_type_id']) ) {
                            $actRelIds['activity_type_id']    = 
                                CRM_Core_OptionGroup::getValue( 'activity_type', 
                                                                'Membership Renewal Reminder', 'name' );
                        }
                        $activityParams['activity_type_id']   = $actRelIds['activity_type_id'];
                        
                        if ( ! isset($actRelIds['activity_status_id']) ) {
                            $actRelIds['activity_status_id']  = 
                                CRM_Core_OptionGroup::getValue( 'activity_status', 'Completed', 'name' );
                        }
                        $activityParams['status_id']          = $actRelIds['activity_status_id'];
                        
                        static $msgTpl = array();
                        if ( ! isset($msgTpl[$memType->renewal_msg_id]) ) {
                            $msgTpl[$memType->renewal_msg_id] = array( );
                            
                            $messageTemplate =& new CRM_Core_DAO_MessageTemplates( );
                            $messageTemplate->id = $memType->renewal_msg_id;
                            if ( $messageTemplate->find(true) ) {
                                $msgTpl[$memType->renewal_msg_id]['subject'] = $messageTemplate->msg_subject;
                                $msgTpl[$memType->renewal_msg_id]['details'] = $messageTemplate->msg_text;
                            }
                            $messageTemplate->free( );
                        }
                        $activityParams['details'] = "Subject: {$msgTpl[$memType->renewal_msg_id]['subject']}
Message: {$msgTpl[$memType->renewal_msg_id]['details']}
";
                        $activity = CRM_Activity_BAO_Activity::create( $activityParams );
                    }
                }
                $memType->free( );
                
            }
            // CRM_Core_Error::debug( 'fEnd', count( $GLOBALS['_DB_DATAOBJECT']['RESULTS'] ) );
        }
    }
}

$obj =& new CRM_UpdateMembershipRecord( );

echo "\n Updating ";
$obj->updateMembershipStatus( );
echo "\n\n Membership records updated. (Done) \n";
