Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 28
0.00% covered (danger)
0.00%
0 / 8
CRAP
0.00% covered (danger)
0.00%
0 / 1
Bitcoin_Wallet
0.00% covered (danger)
0.00%
0 / 28
0.00% covered (danger)
0.00%
0 / 8
132
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
12
 get_post_id
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 get_status
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 get_xpub
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 get_balance
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
6
 get_fresh_addresses
0.00% covered (danger)
0.00%
0 / 16
0.00% covered (danger)
0.00%
0 / 1
2
 get_address_index
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 set_address_index
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2/**
3 * Custom post type in WordPress, keyed with GUID of the wallet.
4 *
5 * TODO: Update the wp_post last modified time when updating metadata.
6 *
7 * @package    brianhenryie/bh-wp-bitcoin-gateway
8 */
9
10namespace BrianHenryIE\WP_Bitcoin_Gateway\API\Addresses;
11
12use Exception;
13use WP_Post;
14
15/**
16 * Facade on WP_Post and post_meta.
17 */
18class Bitcoin_Wallet {
19
20    const POST_TYPE = 'bh-bitcoin-wallet';
21
22    const BALANCE_META_KEY                    = 'bitcoin_wallet_balance';
23    const LAST_DERIVED_ADDRESS_INDEX_META_KEY = 'last_derived_address_index';
24
25    const GATEWAY_IDS_META_KEY = 'payment_gateway_ids';
26
27
28    /**
29     * The actual data as retrieved by WordPress from the database.
30     *
31     * @var WP_Post
32     */
33    protected WP_Post $post;
34
35    /**
36     * Constructor
37     *
38     * @param int $post_id The WordPress post id this wallet is stored under.
39     *
40     * @throws Exception When the supplied post_id is not a post of this type.
41     */
42    public function __construct( int $post_id ) {
43        $post = get_post( $post_id );
44        if ( ! ( $post instanceof WP_Post ) || self::POST_TYPE !== $post->post_type ) {
45            throw new Exception( 'post_id ' . $post_id . ' is not a ' . self::POST_TYPE . ' post object' );
46        }
47
48        $this->post = $post;
49    }
50
51    /**
52     * Used when adding this wallet as a parent of a generated address.
53     *
54     * @return int
55     */
56    public function get_post_id(): int {
57        return $this->post->ID;
58    }
59
60    /**
61     * The current status of the wallet.
62     *
63     * TODO: Mark wallets inactive when removed from a gateway.
64     *
65     * @return string active|inactive
66     */
67    public function get_status(): string {
68        return $this->post->post_status;
69    }
70
71    /**
72     * Return the xpub/ypub/zpub this wallet represents.
73     *
74     * @return string
75     */
76    public function get_xpub(): string {
77        return $this->post->post_excerpt;
78    }
79
80    /**
81     * Get the current balance of this wallet, or null if it has never been checked.
82     *
83     * Must iterate across all addreses and sum them.
84     *
85     * @return ?string
86     */
87    public function get_balance(): ?string {
88        $balance = get_post_meta( $this->post->ID, self::BALANCE_META_KEY, true );
89        return empty( $balance ) ? null : $balance;
90    }
91
92    /**
93     * Find addresses generated from this wallet which are unused and return them as `Bitcoin_Address` objects.
94     *
95     * TODO: Maybe this shouldn't be in here?
96     *
97     * @return Bitcoin_Address[]
98     */
99    public function get_fresh_addresses(): array {
100        $posts = get_posts(
101            array(
102                'post_parent'    => $this->post->ID,
103                'post_type'      => Bitcoin_Address::POST_TYPE,
104                'post_status'    => 'unused',
105                'orderby'        => 'ID',
106                'order'          => 'ASC',
107                'posts_per_page' => -1,
108            )
109        );
110        return array_map(
111            function ( WP_Post $post ) {
112                return new Bitcoin_Address( $post->ID );
113            },
114            $posts
115        );
116    }
117
118    /**
119     * Get the index of the last generated address, so generating new addresses can start higher.
120     *
121     * @return int
122     */
123    public function get_address_index(): int {
124        $index = get_post_meta( $this->post->ID, self::LAST_DERIVED_ADDRESS_INDEX_META_KEY, true );
125        return intval( $index ); // Empty string '' will parse to 0.
126    }
127
128    /**
129     * Save the index of the highest generated address.
130     *
131     * @param int $index Nth address generated index.
132     */
133    public function set_address_index( int $index ): void {
134        update_post_meta( $this->post->ID, self::LAST_DERIVED_ADDRESS_INDEX_META_KEY, $index );
135    }
136}