Completed
Branch FET-9586-add-search-input (524ff8)
by
unknown
436:51 queued 422:19
created

Invoice::send_invoice()   F

Complexity

Conditions 21
Paths > 20000

Size

Total Lines 166
Code Lines 123

Duplication

Lines 6
Ratio 3.61 %

Importance

Changes 0
Metric Value
cc 21
eloc 123
nc 30720
nop 1
dl 6
loc 166
rs 2
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
//Creates the invoice pdf
4
class Invoice {
5
6
	/**
7
	 *
8
	 * @var EE_Registration
9
	 */
10
	private $registration;
11
	/**
12
	 *
13
	 * @var EE_Transaction
14
	 */
15
	private $transaction;
16
	/**
17
	 *
18
	 * @var EE_Payment_Method
19
	 */
20
	private $invoice_payment_method;
21
	private $EE;
0 ignored issues
show
Unused Code introduced by
The property $EE is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
22
	public function __construct($url_link = 0) {
23
24
		if ( $this->registration = EE_Registry::instance()->load_model( 'Registration' )->get_registration_for_reg_url_link( $url_link)) {
0 ignored issues
show
Documentation Bug introduced by
The method get_registration_for_reg_url_link does not exist on object<EEM_Base>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
25
			$this->transaction = $this->registration->transaction();
26
27
			$payment_settings = EE_Config::instance()->gateway->payment_settings;//get_user_meta(EE_Registry::instance()->CFG->wp_user, 'payment_settings', TRUE);
0 ignored issues
show
Unused Code introduced by
$payment_settings is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
Deprecated Code introduced by
The property EE_Config::$gateway has been deprecated.

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
28
			$this->invoice_payment_method = EEM_Payment_Method::instance()->get_one_of_type( 'Invoice' );
29
		} else {
30
			EE_Error::add_error( __( 'Your request appears to be missing some required data, and no information for your transaction could be retrieved.', 'event_espresso' ), __FILE__, __FUNCTION__, __LINE__ );
31
		}
32
33
	}
34
35
	public function send_invoice( $download = FALSE ) {
36
		$template_args = array();
37
		$EE = EE_Registry::instance();
38
39
		//allow the request to override the default theme defined in the invoice settings
40
		$theme_requested = ( isset( $_REQUEST['theme'] ) && $_REQUEST['theme'] > 0 && $_REQUEST['theme'] < 8 ) ? absint( $_REQUEST['theme'] ) : null;
41
		$themes = array(
42
										1 => "simple.css",
43
										2 => "bauhaus.css",
44
										3 => "ejs.css",
45
										4 => "horizon.css",
46
										5 => "lola.css",
47
										6 => "tranquility.css",
48
										7 => "union.css"
49
									);
50
		//Get the CSS file
51
		if( isset( $themes[ $theme_requested ] ) ) {
52
			$template_args['invoice_css'] = $themes[ $theme_requested ];
53
		}else{
54
			$template_args['invoice_css'] = $this->invoice_payment_method->get_extra_meta( 'legacy_invoice_css', TRUE, 'simple.css' );
55
		}
56
57
		if (is_dir(EVENT_ESPRESSO_GATEWAY_DIR . '/invoice')) {
58
			$template_args['base_url'] = EVENT_ESPRESSO_GATEWAY_URL . 'Invoice/lib/templates/';
59
		} else {
60
			$template_args['base_url'] = EE_GATEWAYS . '/Invoice/lib/templates/';
61
		}
62
		$primary_attendee = $this->transaction->primary_registration()->attendee();
63
64
		$template_args['organization'] = $EE->CFG->organization->get_pretty( 'name' );
65
		$template_args['street'] = empty( $EE->CFG->organization->address_2 ) ? $EE->CFG->organization->get_pretty( 'address_1' ) : $EE->CFG->organization->get_pretty( 'address_1' ) . '<br>' . $EE->CFG->organization->get_pretty( 'address_2' );
66
		$template_args['city'] = $EE->CFG->organization->get_pretty( 'city' );
67
		$template_args['state'] = EE_Registry::instance()->load_model( 'State' )->get_one_by_ID( $EE->CFG->organization->STA_ID );
68
		$template_args['country'] = EE_Registry::instance()->load_model( 'Country' )->get_one_by_ID( $EE->CFG->organization->CNT_ISO );
69
		$template_args['zip'] = $EE->CFG->organization->get_pretty( 'zip' );
70
		$template_args['email'] = $EE->CFG->organization->get_pretty( 'email' );
71
72
		$template_args['registration_code'] = $this->registration->reg_code();
73
		$template_args['registration_date'] = $this->registration->date();
74
		$template_args['name'] = $primary_attendee->full_name();
75
		$template_args['attendee_address'] = $primary_attendee->address();
76
		$template_args['attendee_address2'] = $primary_attendee->address2();
77
		$template_args['attendee_city'] = $primary_attendee->city();
78
		$attendee_state = $primary_attendee->state_obj();
79
		if($attendee_state){
80
			$attendee_state_name = $attendee_state->name();
81
		}else{
82
			$attendee_state_name = '';
83
		}
84
		$template_args['attendee_state'] = $attendee_state_name;
85
		$template_args['attendee_zip'] = $primary_attendee->zip();
86
87
		$template_args['ship_name'] = $template_args['name'];
88
		$template_args['ship_address'] = $template_args['attendee_address'];
89
		$template_args['ship_city'] = $template_args['attendee_city'];
90
		$template_args['ship_state'] = $template_args['attendee_state'];
91
		$template_args['ship_zip'] = $template_args['attendee_zip'];
92
93
		$template_args['total_cost'] = number_format($this->transaction->total(), 2, '.', '');
94
		$template_args['transaction'] = $this->transaction;
95
		$template_args['amount_pd'] = $this->transaction->paid();
96
		$template_args['amount_owed'] = $this->transaction->total() - $this->transaction->paid();
97
		$template_args['payments'] = $this->transaction->approved_payments();
98
		$template_args['net_total'] = '';
99
		$template_args['edit_reg_info_url'] = $this->registration->edit_attendee_information_url();
100
		$template_args['retry_payment_url'] = $this->registration->payment_overview_url();
101
		$template_args['show_line_item_description'] = $this->check_if_any_line_items_have_a_description($this->transaction->total_line_item());
102
		if ($template_args['amount_pd'] != $template_args['total_cost']) {
103
			//$template_args['net_total'] = $this->espressoInvoiceTotals( __('SubTotal', 'event_espresso'), $this->transaction->total());//$this->session_data['cart']['REG']['sub_total']);
104
			$tax_items = $this->transaction->tax_items();
105
			if(!empty($tax_items) ){
106
				foreach ($tax_items as $tax) {
107
					$template_args['net_total'] .= $this->espressoInvoiceTotals( $tax->name(), $tax->total());
0 ignored issues
show
Documentation Bug introduced by
The method total does not exist on object<EE_Base_Class>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
108
				}
109
			}
110
111
			$difference = $template_args['amount_pd'] - $template_args['total_cost'];
112
			if ($difference < 0) {
113
				$text = __('Discount', 'event_espresso');
114
			} else {
115
				$text = __('Extra', 'event_espresso');
116
			}
117
			$template_args['discount'] = $this->espressoInvoiceTotals( $text, $difference );
118
		}
119
120
		$template_args['currency_symbol'] = $EE->CFG->currency->sign;
121
		$template_args['template_payment_instructions'] = wpautop(stripslashes_deep(html_entity_decode($this->invoice_payment_method->get_extra_meta( 'pdf_instructions', TRUE ), ENT_QUOTES)));
122
		$template_args['shameless_plug'] = apply_filters( 'FHEE_Invoice__send_invoice__shameless_plug',true );
123
		if(isset($_GET['receipt'])){
124
			//receipt-specific stuff
125
			$events_for_txn = EEM_Event::instance()->get_all(array(array('Registration.TXN_ID'=>$this->transaction->ID())));
126
			$ticket_line_items_per_event = array();
127
			$registrations_per_line_item = array();
128
			$venues_for_events = array();
129
			foreach($events_for_txn as $event_id => $event){
130
				$line_items_for_this_event = EEM_Line_Item::instance()->get_all(array(array('Ticket.Datetime.EVT_ID'=>$event_id,'TXN_ID'=>$this->transaction->ID())));
131
				$ticket_line_items_per_event[$event_id] = $line_items_for_this_event;
132
				foreach($line_items_for_this_event as $line_item_id => $line_item){
133
					$ticket = $line_item->ticket();
0 ignored issues
show
Documentation Bug introduced by
The method ticket does not exist on object<EE_Base_Class>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
134
					$registrations_for_this_ticket = EEM_Registration::instance()->get_all(array(array('TKT_ID'=>$ticket->ID(),'TXN_ID'=>$this->transaction->ID())));
135
					$registrations_per_line_item[$line_item_id] = $registrations_for_this_ticket;
136
				}
137
				$venues_for_events = array_merge($venues_for_events, $event->venues());
0 ignored issues
show
Documentation Bug introduced by
The method venues does not exist on object<EE_Base_Class>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
138
			}
139
			$tax_total_line_item = EEM_Line_Item::instance()->get_one(array(array('TXN_ID'=>$this->transaction->ID(),'LIN_type'=>  EEM_Line_Item::type_tax_sub_total)));
140
			$questions_to_skip = array(EEM_Attendee::system_question_fname,EEM_Attendee::system_question_lname,  EEM_Attendee::system_question_email);
141
142
143
			$template_args['events_for_txn'] = $events_for_txn;
144
			$template_args['ticket_line_items_per_event'] = $ticket_line_items_per_event;
145
			$template_args['registrations_per_line_item'] = $registrations_per_line_item;
146
			$template_args['venues_for_events'] = $venues_for_events;
147
			$template_args['tax_total_line_item'] = $tax_total_line_item;
148
			$template_args['questions_to_skip'] = $questions_to_skip;
149
//			d($template_args);
150
			$template_args['download_link'] = $this->registration->receipt_url('download');
151
		}else{
152
			//it's just an invoice we're accessing
153
			$template_args['download_link'] = $this->registration->invoice_url('download');
154
		}
155
156
		//Get the HTML as an object
157
		$templates_relative_path = 'modules/gateways/Invoice/lib/templates/';
158
		$template_header = EEH_Template::locate_template( $templates_relative_path . 'invoice_header.template.php', $template_args, TRUE, TRUE );
159
		if(isset($_GET['receipt'])){
160
			$template_body = EEH_Template::locate_template( $templates_relative_path . 'receipt_body.template.php', $template_args, TRUE, TRUE );
161
		}else{
162
			$template_body = EEH_Template::locate_template( $templates_relative_path . 'invoice_body.template.php', $template_args, TRUE, TRUE );
163
		}
164
165
166
		$template_footer = EEH_Template::locate_template( $templates_relative_path . 'invoice_footer.template.php', $template_args, TRUE, TRUE );
167
168
		$copies =  ! empty( $_REQUEST['copies'] ) ? $_REQUEST['copies'] : 1;
169
170
		$content = $this->espresso_replace_invoice_shortcodes($template_header);
171
		for( $x = 1; $x <= $copies; $x++ ) {
172
			$content .= $this->espresso_replace_invoice_shortcodes($template_body);
173
		}
174
		$content .= $this->espresso_replace_invoice_shortcodes($template_footer);
175
176
		//Check if debugging or mobile is set
177
		if (!empty($_REQUEST['html'])) {
178
			echo $content;
179
			exit(0);
180
		}
181
		$invoice_name = $template_args['organization'] . ' ' . __('Invoice #', 'event_espresso') . $template_args['registration_code'] . __(' for ', 'event_espresso') . $template_args['name'];
182
		$invoice_name = str_replace( ' ', '_', $invoice_name );
183
		//Create the PDF
184
		if(array_key_exists('html',$_GET)){
185
			echo $content;
186
		}else{
187
			//only load dompdf if nobody else has yet...
188 View Code Duplication
			if( ! defined('DOMPDF_DIR')){
189
				define('DOMPDF_ENABLE_REMOTE', TRUE);
190
				define('DOMPDF_ENABLE_JAVASCRIPT', FALSE);
191
				define('DOMPDF_ENABLE_CSS_FLOAT', TRUE);
192
				require_once(EE_THIRD_PARTY . 'dompdf/dompdf_config.inc.php');
193
			}
194
			$dompdf = new DOMPDF();
195
			$dompdf->load_html($content);
196
			$dompdf->render();
197
			$dompdf->stream($invoice_name . ".pdf", array( 'Attachment' => $download ));
198
		}
199
		exit(0);
200
	}
201
	/**
202
	 * Checks if this line item, or any of its children, actually has a description.
203
	 * If none do, then the template can decide to not show any description column
204
	 * @param EE_Line_Item $line_item
205
	 * @return boolean
206
	 */
207
	function check_if_any_line_items_have_a_description(EE_Line_Item $line_item){
208
		if($line_item->desc()){
209
			return true;
210
		}else{
211
			foreach($line_item->children() as $child_line_item){
212
				if($this->check_if_any_line_items_have_a_description($child_line_item)){
213
					return true;
214
				}
215
			}
216
			//well, if I and my children don't have descriptions, I guess not
217
			return false;
218
		}
219
	}
220
221
//Perform the shortcode replacement
222
	function espresso_replace_invoice_shortcodes( $content ) {
223
224
		$EE = EE_Registry::instance();
225
		//Create the logo
226
		$invoice_logo_url = $this->invoice_payment_method->get_extra_meta('pdf_logo_image', TRUE,  $EE->CFG->organization->logo_url );
227
		if (!empty($invoice_logo_url)) {
228
			$image_size = getimagesize($invoice_logo_url);
229
			$invoice_logo_image = '<img class="logo screen" src="' . $invoice_logo_url . '" ' . $image_size[3] . ' alt="logo" /> ';
230
		} else {
231
			$invoice_logo_image = '';
232
		}
233
		$SearchValues = array(
234
				"[organization]",
235
				"[registration_code]",
236
				"[transaction_id]",
237
				"[name]",
238
				"[base_url]",
239
				"[download_link]",
240
				"[invoice_logo_image]",
241
				"[street]",
242
				"[city]",
243
				"[state]",
244
				"[zip]",
245
				"[email]",
246
				"[vat]",
247
				"[registration_date]",
248
				"[instructions]",
249
		);
250
		$primary_attendee = $this->transaction->primary_registration()->attendee();
251
		$org_state = EE_Registry::instance()->load_model( 'State' )->get_one_by_ID( $EE->CFG->organization->STA_ID );
252
		if($org_state){
253
			$org_state_name = $org_state->name();
254
		}else{
255
			$org_state_name = '';
256
		}
257
		$ReplaceValues = array(
258
				$EE->CFG->organization->get_pretty( 'name' ),
259
				$this->registration->reg_code(),
260
				$this->transaction->ID(),
261
				$primary_attendee->full_name(),
262
				(is_dir(EVENT_ESPRESSO_GATEWAY_DIR . '/invoice')) ? EVENT_ESPRESSO_GATEWAY_URL . 'Invoice/lib/templates/' : EE_GATEWAYS_URL . 'Invoice/lib/templates/',
263
				$this->registration->invoice_url(),//home_url() . '/?download_invoice=true&amp;id=' . $this->registration->reg_url_link(),
264
				$invoice_logo_image,
265
				empty( $EE->CFG->organization->address_2 ) ? $EE->CFG->organization->get_pretty( 'address_1' ) : $EE->CFG->organization->get_pretty( 'address_1' ) . '<br>' . $EE->CFG->organization->get_pretty( 'address_2' ),
266
				$EE->CFG->organization->get_pretty( 'city' ),
267
				$org_state_name,
268
				$EE->CFG->organization->get_pretty( 'zip' ),
269
				$EE->CFG->organization->get_pretty( 'email' ),
270
				$EE->CFG->organization->vat,
271
				$this->registration->get_i18n_datetime( 'REG_date', get_option( 'date_format' ) ),
272
				$this->invoice_payment_method->get_extra_meta( 'pdf_instructions', TRUE ),
273
		);
274
275
		return str_replace($SearchValues, $ReplaceValues, $content);
276
	}
277
278
	public function espressoLoadData($items) {
279
		$lines = $items;
280
		$data = array();
281
		foreach ($lines as $line)
282
			$data[] = explode(';', chop($line));
283
284
		return $data;
285
	}
286
287
288
289
	public function espressoInvoiceTotals($text, $total_cost) {
290
291
		$html = '';
292
		if ($total_cost < 0) {
293
			$total_cost = (-1) * $total_cost;
294
		}
295
		$find = array( ' ' );
296
		$replace = array( '-' );
297
		$row_id = strtolower( str_replace( $find, $replace, $text ));
298
		$html .= '<tr id="'.$row_id.'-tr"><td colspan="4">&nbsp;</td>';
299
		$html .= '<td class="item_r">' . $text . '</td>';
300
		$html .= '<td class="item_r">' . $total_cost . '</td>';
301
		$html .= '</tr>';
302
		return $html;
303
	}
304
305
}
306